In this exercise we will learn:
This example has two 1-D chare arrays - KeyValueStore and KeyValueClient
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.