{foodecl}
program jacobi
class JacobiMain : MainChare;
class JacobiWorker : ChareArray1D;
obj workers : JacobiWorker[M];
param lb : double[N];
param rb : double[N];
begin
for iter = 1 to MAX_ITER
foreach i in workers
(lb[i], rb[i]) <- workers[i].produceBorders();
workers[i].compute(lb[i+1], rb[i-1]);
end-foreach
end-for
end
The class JacobiMain does not need any sequential code, so the only sequential code are in JacobiWorker.h and JacobiWorker.C. Note that JacobiWorker.h contains only the sequential portion of JacobiWorker's declaration.
{foodecl}
#define N 512
#define M 16
int currentArray;
double localData[2][M][N];
double localLB[N];
double localRB[N];
int myLeft,myRight,myUpper,myLower;
void initialize();
void compute(double lghost[], double rghost[]);
void produceBorders(outport lb,outport rb);
double abs(double d);
Similarly, the sequential C code will be integrated into the generated C file. Below is part of the sequential C code taken from JacobiWorker.C to show how consumed parameters (rghost and lghost in JacobiWorker::compute) and produced parameters (lb and rb in JacobiWorker::produceBorders) are handled.
{foodecl}
void JacobiWorker::compute(double rghost[], double lghost[]){
/* local computation for updating elements*/
}
void JacobiWorker::produceBorders(outport lb, outport rb){
produce(lb,localData[currentArray][myLeft],myLower-myUpper+1);
produce(rb,localData[currentArray][myRight],myLower-myUpper+1);
}
The user compile these input files with the following command:
{foodecl}
> orchc jacobi.or
The compiler generates the parallel code for sending out messages, organizing flow of control, and then it looks for sequential code files for the classes declared, namely JacobiMain and JacobiWorker, and integrates them into the final output: jacobi.h, jacobi.C and jacobi.ci, which is a Charm++ program and can be built the way a Charm++ program is built.
October 08, 2008
Charisma Homepage
Charm Homepage