Parallel Key-Value Store-Retrieval

In this exercise we will learn:

This example has two 1-D chare arrays - KeyValueStore and KeyValueClient

  1. Each element of KeyValueStore array, stores pairs for keys in the range [idx*M, (idx+1)*M-1], where idx is the element index in the array and M is the number of keys stored per chare array element.
  2. KeyValueClient array has a method called run(), which generates K random keys and then requests for the values of those keys from their respective owners.
  3. Once all the values of the requested keys have been received, the chare array elements contributes to a reduction indicating that it is done.
  4. The reduction target is a function that terminates the program.

Note that even though each client chare knows how many requests it is making, the keyValueStore element chares do not know how many requests they will each get.
This could pose some problems in MPI; but its OK in Charm++. Even after you contribute into the reduction, the keyValueStore chares on your processor can continue responding to requests.

Begin with incomplete code below (and can be downloaded here).

         main.ci:

            /**
             *
             *   Charm Tutorial Exercise
             *   Key-value store, reduction, sdag
             *
             *
             *
             **/
            
            mainmodule main {
            
               readonly CProxy_Main mainProxy;
               readonly CProxy_KeyValueStore kvstoreProxy;
               readonly CProxy_KeyValueClient kvclientProxy;
               readonly int N;
               readonly int M;
               readonly int K;
            
               mainchare Main {
                  entry Main(CkArgMsg *m);
                  entry [reductiontarget] void finish();
               };
            
               array [1D] KeyValueClient {
                  entry KeyValueClient();
                  entry void response(int refnum, int value);
                  entry void run(){
                     serial {
                        for(i=0; i<K; i++){
                           int key = rand()%(M*N);
                           kvpairs[i].key = key;
                        }
                     }
                     /************
                        add code here
                           1. send the request for values for all the keys in the vector kvpairs
                                    use method KeyValueStore::request(..) for this
                           2. the corresponding array elements of KeyValueStore Array will send
                                    the values back by calling the KeyValueClient::response(..) that will
                                    also have the request refnum.
                                    save the value at the correct index (by using refnum) of the kvpairs vector   
                           3. once all the responses have been received, do a reduction with Main::finish() as
                                    the reduction target  which will exit the program
                     ************/
                  };
               };
            
               array [1D] KeyValueStore {
                  entry KeyValueStore(void);
                  entry void request(int refnum, int k, int reqIdx);
               };
            };
        













































         main.C:

    /**
     *      
     *      Charm Tutorial Exercise
     *      key-value store, reduction, sdag
     *
     *      
     **/
    
    #include <vector>
    #include <map>
    #include <math.h>
    #include <assert.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include "charm++.h"
    #include "main.decl.h"
    
    using namespace std;
    /*readonly*/ CProxy_Main mainProxy;
    /*readonly*/ CProxy_KeyValueStore kvstoreProxy;
    /*readonly*/ CProxy_KeyValueClient kvclientProxy;
    /*readonly*/ int N; //number of chares in KeyValueStore array
    /*readonly*/ int M; //keys stored per chare
    /*readonly*/ int K; //number of key requests from a chare
    
    struct KeyValue{
       int key;
       int value;
    };
    
    class Main : public CBase_Main
    {
      public:
       Main(CkArgMsg *m){
          mainProxy = thisProxy;
          N = CkNumPes();
          M = 10000;
          K = 10;
    
          //Initialize the KeyValueStoreArray
          kvstoreProxy = CProxy_KeyValueStore::ckNew(N);
    
          //Initialize the KeyValueClientArray
          kvclientProxy = CProxy_KeyValueClient::ckNew(N);
    
          //call method run on all the elements of KeyValueClient Array
          kvclientProxy.run();

       };
    
       void finish(){
          ckout << "all responses received ... exiting ..." << endl;
          CkExit();
       }
    };
    
    class KeyValueStore : public CBase_KeyValueStore{
      private:
       std::map<int, int> kvmap;
    
      public:
    
       KeyValueStore(){
          for(int i=0; i<M; i++)
             kvmap[thisIndex*M + i] = rand();
       }
    
       KeyValueStore(CkMigrateMessage* m) {};
    
       void request(int refnum, int key, int reqIdx){
          kvclientProxy[reqIdx].response(refnum, kvmap[key]);
       }
    };
    class KeyValueClient : public CBase_KeyValueClient
    {
       KeyValueClient_SDAG_CODE
      private:
       KeyValue* kvpairs;
       int i;
    
      public:
    
       KeyValueClient(){
          kvpairs = new KeyValue[K];
       };
    
       KeyValueClient(CkMigrateMessage* m) {};
    };
    
    #include "main.def.h"



















































































The solution can be found here.