Charm++ Tutorial Presented by: Laxmikant V. Kale Kumaresh Pattabiraman Chee Wai Lee
Overview Introduction – Developing parallel applications – Virtualization – Message Driven Execution Charm++ Features – Chares and Chare Arrays – Parameter Marshalling – Examples Tools – LiveViz – Parallel Debugger – Projections More Charm++ features – Structured Dagger Construct – Adaptive MPI – Load Balancing 2 Conclusion
Outline Introduction Charm++ features – Chares and Chare Arrays – Parameter Marshalling – Examples Tools – LiveViz – Parallel Debugger – Projections More Charm++ Features – Structured Dagger Construct – Adaptive MPI – Load Balancing 3 Conclusion
Developing a Parallel Application Seek optimal division of labor between “system” and programmer Decomposition done by programmer, everything else automated Decomposition Automation Mapping Charm++ Scheduling Specialization 4
Virtualization: Object-based Decomposition Divide the computation into a large number of pieces – Independent of number of processors – Typically larger than number of processors Let the system map objects to processors 5
Object-based Parallelization User is only concerned with interaction between objects System implementation User View 6
Message-Driven Execution Objects communicate asynchronously through remote method invocation Encourages non-deterministic execution Benefits: – Communication latency tolerance – Logical structure for scheduling 7
Message-Driven Execution in Charm++ CkExit() x y Objects y->f() ?? Scheduler Scheduler Message Q Message Q 8
Other Charm++ Characteristics Methods execute one at a time No need for locks Expressing flow of control may be difficult 9
Outline Introduction Charm++ features – Chares and Chare Arrays – Parameter Marshalling – Examples Tools – LiveViz – Parallel Debugger – Projections More Charm++ Features – Structured Dagger Construct – Adaptive MPI – Load Balancing 10 Conclusion
Chares – Concurrent Objects Can be dynamically created on any available processor Can be accessed from remote processors Send messages to each other asynchronously Contain “entry methods” 11
“Hello World” // hello.C file // hello.C file // hello.ci file // hello.ci file #include “hello.decl.h” #include “hello.decl.h” mainmodule mainmodule hello { class mymain : public Chare class mymain : public Chare { { mainchare mainchare mymain { public: public: entry entry mymain(CkArgMsg *m); mymain(CkArgMsg *m) mymain(CkArgMsg *m) }; { { }; ckout <<“Hello World”<<endl; ckout <<“Hello World”<<endl; CkExit(); CkExit(); } } Generates: }; }; #include “hello.def.h” #include “hello.def.h” hello.decl.h hello.def.h 12
Compile and run the program Compiling • charmc <options> <source file> • -o, -g, -language, -module, -tracemode pgm: pgm.ci pgm.h pgm.C charmc pgm.ci Example Nodelist File: charmc pgm.C group main ++shell ssh charmc –o pgm pgm.o –language charm++ host Host1 host Host2 To run a CHARM++ program named ``pgm'' on four processors, type: charmrun pgm +p4 <params> Nodelist file (for network architecture) • list of machines to run the program • host <hostname> <qualifiers> 13
Charm++ solution: Proxy classes Proxy class generated for each chare class – For instance, CProxy_Y is the proxy class generated for chare class Y. – Proxy objects know where the real object is – Methods invoked on this object simply put the data in an “envelope” and send it out to the destination Given a proxy p, you can invoke methods – p.method(msg); 14
Chare Arrays • Array of Objects of the same kind • Each one communicates with the next one • Individual chares – cumbersome and not practical Chare Array: – with a single global name for the collection – each member addressed by an index – mapping of element objects to processors handled by the system 15
Chare Arrays A A A A A User’s view [0] [1] [2] [3] [..] System view A A [0] [1] A A [0] [1] 16
Array Hello mainmodule m { mainmodule class Hello : public class Hello : public CBase_Hello CBase_Hello readonly readonly CProxy_mymain CProxy_mymain { { mainProxy; mainProxy; readonly readonly int nElements; int nElements; public: public: mainchare mainchare mymain { …. } { …. } Hello(CkMigrateMessage *m){} Hello(CkMigrateMessage *m){} array [1D] array [1D] Hello { entry Hello (void); entry (void); Hello(); Hello(); entry void sayHi ( int HiNo ); entry void ); Class mymain : public Chare Class mymain : public Chare void sayHi(int hiNo); void sayHi(int hiNo); }; { { }; }; }; mymain() { mymain() { Class Declaration (.ci) file nElements=4; nElements=4; mainProxy = mainProxy = thisProxy thisProxy; ; CProxy_ CProxy_ Hello p = p = CProxy_ CProxy_ Hello ::ckNew(nElements); ::ckNew(nElements); //Have element 0 say “hi” In mymain:: mymain() p[0].sayHi(12345); p[0].sayHi(12345); } } } } 17
Array Hello Element index void Hello::sayHi(int hiNo) void Hello::sayHi(int hiNo) { { ckout << hiNo <<"from element" << thisIndex ckout << hiNo <<"from element" << thisIndex << endl; << endl; if (thisIndex < nElements-1) if (thisIndex < nElements-1) Array //Pass the hello on: //Pass the hello on: Proxy thisProxy[thisIndex+1].sayHi(hiNo+1); thisProxy[thisIndex+1].sayHi(hiNo+1); else else //We've been around once-- we're done. //We've been around once-- we're done. mainProxy.done(); mainProxy.done(); } } void mymain::done(void){ void mymain::done(void){ CkExit(); CkExit(); } } Read-only 18
Sorting numbers Sort n integers in increasing order. Create n chares, each keeping one number. In every odd iteration chares numbered 2i swaps with chare 2i+1 if required. In every even iteration chares 2i swaps with chare 2i-1 if required. After each iteration all chares report to the mainchare. After everybody reports mainchares signals next iteration. Sorting completes in n iterations. Even round: Odd round: 19
Array Sort sort.ci mainmodule sort{ sort.h class sort : public CBase_sort{ class sort : public CBase_sort{ readonly CProxy_myMain mainProxy; readonly int nElements; private: private: int myValue; int myValue; mainchare myMain { public: public: entry myMain(CkArgMsg *m); sort() ; sort() ; entry void swapdone(void); sort(CkMigrateMessage *m); sort(CkMigrateMessage *m); }; array [1D] sort{ void setValue(int number); void setValue(int number); entry sort(void); void swap(int round_no); void swap(int round_no); entry void setValue(int myvalue); swapcount=0; swapcount=0; void swapReceive(int from_index, void swapReceive(int from_index, entry void swap(int round_no); roundsDone=0; roundsDone=0; int value); int value); entry void swapReceive(int from_index, mainProxy = thishandle; mainProxy = thishandle; myMain::myMain() }; }; int value); CProxy_sort arr = CProxy_sort arr = }; CProxy_sort::ckNew(nElements); CProxy_sort::ckNew(nElements); }; for(int i=0;i<nElements;i++) for(int i=0;i<nElements;i++) arr[i].setValue(rand()); arr[i].setValue(rand()); 20 arr.swap(0); arr.swap(0);
Array Sort (continued ...) void sort::swap(int roundno) void sort::swap(int roundno) { { bool sendright=false; bool sendright=false; if (roundno%2==0 && thisIndex%2==0|| roundno%2==1 && thisIndex%2==1) if (roundno%2==0 && thisIndex%2==0|| roundno%2==1 && thisIndex%2==1) sendright=true; // sendright=true; //sendright is true if I have to send to right sendright is true if I have to send to right if((sendright && thisIndex==nElements-1) || (!sendright && thisIndex==0)) if((sendright && thisIndex==nElements-1) || (!sendright && thisIndex==0)) void sort::swapReceive(int from_index, int value) void sort::swapReceive(int from_index, int value) mainProxy.swapdone(); mainProxy.swapdone(); { { else{ else{ if(from_index==thisIndex-1 && value>myValue) if(from_index==thisIndex-1 && value>myValue) if(sendright) if(sendright) void myMain::swapdone(void) { void myMain::swapdone(void) { myValue=value; myValue=value; thisProxy[thisIndex+1].swapReceive(thisIndex, myValue); thisProxy[thisIndex+1].swapReceive(thisIndex, myValue); if(from_index==thisIndex+1 && value<myValue) if(from_index==thisIndex+1 && value<myValue) else else if (++swapcount==nElements) { if (++swapcount==nElements) { thisProxy[thisIndex-1].swapReceive(thisIndex, myValue); thisProxy[thisIndex-1].swapReceive(thisIndex, myValue); myValue=value; myValue=value; swapcount=0; swapcount=0; } } mainProxy.swapdone(); mainProxy.swapdone(); roundsDone++; roundsDone++; } } } } if (roundsDone==nElements) if (roundsDone==nElements) Error! ! CkExit(); CkExit(); else else arr.swap(roundsDone); arr.swap(roundsDone); } } } } 21
Remember : Message passing is asynchronous . Messages can be delivered out of order . swap swap swapReceive 3 2 3 swapReceive 22
Recommend
More recommend