Homework 12 Solutions

22C:116, Fall 1995

Douglas W. Jones
  1. Part A: Translate the following Charm to equivalent code for a conventional thread that uses blocking buffered message passing with the primitives send and receive.

            char C(A,B)
            {
                   H(A + B);
                   R(A - B);
            }
    

    The Solution:

            thread C:
               loop
                   wait for message containing A,B
                   send A+B to thread H
                   send A-B to thread R
               endloop
    

    Part B: Write the code for a Charm server:

    The Solution:

            server:
               loop
                   await message M
                   let P = M.tag
                   let Q = M.body
                   call P(Q)
               endloop
    

  2. Part A: How would you detect that the load on such a system was unbalanced?

    The Solution: The percentage of time a Charm server process is not blocked awaiting incoming messages is a measure of the local load. Comparing these loads would be a reasonable way to detect imbalance.

    Part B: How would you determine which machine in the system should shed part of its load and which machine would accept that excess work?

    A Solution: If Charm servers had access to their local load and if Charm servers had a protocol that allowed a server to request local load figures from another, servers that are sufficiently idle (that is, servers with a sufficiently low local load) could request loading figures from some set of neighbors and, if a neighbor is sufficiently overloaded, initiate load transfer.

    Part C: How would you actually move the processing of a Char from one machine to another?

    The Solution: Between instantiations, the state of a Char is entirely stored in the static variables of that Char. Thus, as long as the Char's server is running and not calling that Char, its state is cleanly encapsulated. Once the server has picked a Char to offload and some other server has volunteered to accept that char, the first server can simply send the static state record to the second server. Having done this, the messages addressed to that Char must be forwarded. Local forwarding can be done updating the server(H) function locally, and then making the following change to the server:

            server:
               loop
                   await message M
                   if M.dst ≠ server(M.tag) then
                       -- forwarding required
                       M.dst = server(M.tag)
                       send(M)
                   else
                       -- normal local processing
                       let P = M.tag
                       let Q = M.body
                       call P(Q)
                   endif
               endloop
    
    Even if it takes a long time to distribute forwarding address notices to all Charm kernels in the system, this guarantees that all messages will be delivered.