charm AT lists.siebelschool.illinois.edu
Subject: Charm++ parallel programming system
List archive
- From: SAGAR SHEDGE <sagar.shedge92 AT gmail.com>
- To: charm AT cs.uiuc.edu
- Subject: [charm] About syntax
- Date: Fri, 5 Aug 2011 18:12:35 +0530
- List-archive: <http://lists.cs.uiuc.edu/pipermail/charm>
- List-id: CHARM parallel programming system <charm.cs.uiuc.edu>
Respected Sir/Mam,
I was reading example from tests/charm++/kNeighbour/ , where I seen one syntax in .ci file.
group MyMap : CkArrayMap{
entry MyMap(int);
};
In .C file you have inherited MyMap from CkArrayMap and overloaded pure virtual function int procNum(int arrayHdl, const CkArrayIndex &idx).
I have query as follows :
1. I want to know why you have written CkArrayMap there , as CkArrayMap structure is internally used by charm++ to map array element to home processor.
2. In which cases we have write it?
3. What is purpose of procNum(int arrayHdl, const CkArrayIndex &idx). i.e. what you have done in that function? Also I am sending you both files.
--
Sagar Dilip Shedge,
C-DAC R&D,
Pune.
With Regards.
#include "kNeighbor.decl.h"
#include <stdio.h>
#include <stdlib.h>
#define STRIDEK 3
#define CALCPERSTEP 100
#define WRAPROUND 1
#define ALLCROSSNODE 0
#define BLOCKMAPPING 1
#define USE_ARRAY_REDUCTION 0
#define DEBUG 0
#define REUSE_ITER_MSG 0
CProxy_Main mainProxy;
int gMsgSize;
class toNeighborMsg: public CMessage_toNeighborMsg {
public:
int *data;
int size;
int fromX;
int nID;
public:
toNeighborMsg() {};
toNeighborMsg(int s): size(s) { init(); }
void setMsgSrc(int X, int id) {
fromX = X;
nID = id;
}
void init() {
for (int i=0; i<size; i++)
data[i] = i;
}
int sum() {
int s;
for (int i=0; i<size; i++)
s += data[i];
return s;
}
};
//#define MSGSIZECNT 1
int cmpFunc(const void *a, const void *b){
if(*(double *)a < *(double *)b) return -1;
if(*(double *)a > *(double *)b) return 1;
return 0;
}
class Main: public CBase_Main {
public:
CProxy_Block array;
//static int msgSizeArr[MSGSIZECNT];
int numSteps;
int currentStep;
int currentMsgSize;
int totalElems;
int elementsRecved;
double totalTime;
double maxTime;
double minTime;
double *timeRec;
double gStarttime;
public:
Main(CkArgMsg *m) {
mainProxy = thisProxy;
if (m->argc!=4) {
CkPrintf("Usage: %s <#elements> <#iterations> <msg size>\n", m->argv[0]);
delete m;
CkExit();
}
int numElems = atoi(m->argv[1]);
numSteps = atoi(m->argv[2]);
currentMsgSize = atoi(m->argv[3]);
#if REUSE_ITER_MSG
gMsgSize = currentMsgSize;
#endif
currentStep = -1;
totalElems = numElems;
timeRec = new double[numSteps];
CProxy_MyMap myMap = CProxy_MyMap::ckNew(totalElems);
CkArrayOptions opts(totalElems);
opts.setMap(myMap);
array = CProxy_Block::ckNew(totalElems, opts);
CkCallback *cb = new CkCallback(CkIndex_Main::nextStep(NULL), thisProxy);
array.ckSetReductionClient(cb);
beginIteration();
}
void beginIteration() {
currentStep++;
if (currentStep==numSteps) {
CkPrintf("kNeighbor program finished!\n");
//CkCallback *cb = new CkCallback(CkIndex_Main::terminate(NULL), thisProxy);
//array.ckSetReductionClient(cb);
//array.printSts(numSteps);
terminate(NULL);
return;
//CkExit();
}
elementsRecved = 0;
totalTime = 0.0;
maxTime = 0.0;
minTime = 3600.0;
//int msgSize = msgSizeArr[currentStep%MSGSIZECNT];
//int msgSize = msgSizeArr[rand()%MSGSIZECNT];
//currentMsgSize = msgSize;
gStarttime = CmiWallTimer();
#if REUSE_ITER_MSG
for (int i=0; i<totalElems; i++)
array(i).commWithNeighbors();
#else
for (int i=0; i<totalElems; i++)
array(i).commWithNeighbors(currentMsgSize);
#endif
//array.commWithNeighbors(currentMsgSize);
}
void terminate(CkReductionMsg *msg){
delete msg;
double total = 0.0;
for (int i=0; i<numSteps; i++) timeRec[i] = timeRec[i]*1e6;
qsort(timeRec, numSteps, sizeof(double), cmpFunc);
printf("Time stats: lowest: %f, median: %f, highest: %f\n", timeRec[0], timeRec[numSteps/2], timeRec[numSteps-1]);
int samples = 100;
if(numSteps<=samples) samples = numSteps-1;
for (int i=0; i<samples; i++) total += timeRec[i];
total /= samples;
CkPrintf("The average time for each %d-kNeighbor iteration with msg size %d is %f (us)\n", STRIDEK, currentMsgSize, total);
CkExit();
}
void nextStep_plain(double iterTime) {
elementsRecved++;
totalTime += iterTime;
maxTime = maxTime>iterTime?maxTime:iterTime;
minTime = minTime<iterTime?minTime:iterTime;
if (elementsRecved == totalElems) {
double wholeStepTime = CmiWallTimer() - gStarttime;
timeRec[currentStep] = wholeStepTime/CALCPERSTEP;
//CkPrintf("Step %d with msg size %d finished: max=%f, total=%f\n", currentStep, currentMsgSize, maxTime/CALCPERSTEP, wholeStepTime/CALCPERSTEP);
beginIteration();
}
}
void nextStep(CkReductionMsg *msg) {
maxTime = *((double *)msg->getData());
delete msg;
double wholeStepTime = CmiWallTimer() - gStarttime;
timeRec[currentStep] = wholeStepTime/CALCPERSTEP;
//CkPrintf("Step %d with msg size %d finished: max=%f, total=%f\n", currentStep, currentMsgSize, maxTime/CALCPERSTEP, wholeStepTime/CALCPERSTEP);
beginIteration();
}
};
//int Main::msgSizeArr[MSGSIZECNT] = {16, 32, 128, 256, 512, 1024, 2048, 4096};
//int Main::msgSizeArr[MSGSIZECNT] = {10000};
class MyMap : public CkArrayMap{
private:
int totalElems;
public:
MyMap(int n) {
totalElems = n;
}
MyMap(CkMigrateMessage *m){}
/*int registerArray(CkArrayMapRegisterMessage *m){
delete m;
return 0;
}*/
int procNum(int arrayHdl, const CkArrayIndex &idx){
int elem = *(int *)idx.data();
int penum;
#if BLOCKMAPPING
int blkSize = totalElems/CkNumPes();
penum = (elem/blkSize)%CkNumPes();
#elif NODECYCLICMAPPING
int nid = (elem/CkMyNodeSize())%CkNumNodes();
int cid = elem % CkMyNodeSize();
penum = CkNodeFirst(nid)+cid;
#else
//Default is RoundRobin Mapping
penum = elem%CkNumPes();
#endif
return penum;
}
};
//#define WORKSIZECNT 5
#define WORKSIZECNT 1
//no wrap around for sending messages to neighbors
class Block: public CBase_Block {
public:
/** actual work size is of workSize^3 */
static int workSizeArr[WORKSIZECNT];
int totalElems;
int numNeighbors;
int neighborsRecved;
int *neighbors;
double *recvTimes;
double startTime;
int random;
int curIterMsgSize;
int curIterWorkSize;
int internalStepCnt;
int sum;
#if REUSE_ITER_MSG
toNeighborMsg **iterMsg;
#endif
public:
Block(int numElems) {
//srand(thisIndex.x+thisIndex.y);
totalElems = numElems;
#if WRAPROUND
numNeighbors = 2*STRIDEK;
neighbors = new int[numNeighbors];
recvTimes = new double[numNeighbors];
int nidx=0;
//setting left neighbors
for (int i=thisIndex-STRIDEK; i<thisIndex; i++, nidx++) {
int tmpnei = i;
while (tmpnei<0) tmpnei += totalElems;
neighbors[nidx] = tmpnei;
}
//setting right neighbors
for (int i=thisIndex+1; i<=thisIndex+STRIDEK; i++, nidx++) {
int tmpnei = i;
while (tmpnei>=totalElems) tmpnei -= totalElems;
neighbors[nidx] = tmpnei;
}
#elif ALLCROSSNODE
if(CkNumNodes()==1){
if(thisIndex==0){
CkPrintf("This version has to run with more than 2 nodes!\n");
CkExit();
}
return;
}
numNeighbors = CkNumNodes()-1;
neighbors = new int[numNeighbors];
recvTimes = new double[numNeighbors];
for(int i=0; i<numNeighbors; i++){
neighbors[i] = (thisIndex+(i+1)*CmiMyNodeSize())%CkNumPes();
}
#else
//calculate the neighbors this element has
numNeighbors = 0;
numNeighbors += thisIndex - MAX(0, thisIndex-STRIDEK); //left
numNeighbors += MIN(totalElems-1, thisIndex+STRIDEK)-thisIndex; //right
neighbors = new int[numNeighbors];
recvTimes = new double[numNeighbors];
int nidx=0;
for (int i=MAX(0, thisIndex-STRIDEK); i<thisIndex; i++, nidx++) neighbors[nidx]=i;
for (int i=thisIndex+1; i<=MIN(totalElems-1, thisIndex+STRIDEK); i++, nidx++) neighbors[nidx] = i;
#endif
for (int i=0; i<numNeighbors; i++)
recvTimes[i] = 0.0;
#if REUSE_ITER_MSG
iterMsg = new toNeighborMsg *[numNeighbors];
for (int i=0; i<numNeighbors; i++)
iterMsg[i] = NULL;
#endif
#if DEBUG
CkPrintf("Neighbors of %d: ", thisIndex);
for (int i=0; i<numNeighbors; i++)
CkPrintf("%d ", neighbors[i]);
CkPrintf("\n");
#endif
//CkPrintf("Elem [%d] on proc %d (node=%d, rank=%d)\n", thisIndex, CkMyPe(), CkMyNode(), CkMyRank());
random = thisIndex*31+73;
}
~Block() {
delete [] neighbors;
delete [] recvTimes;
#if REUSE_ITER_MSG
delete [] iterMsg;
#endif
}
Block(CkMigrateMessage *m) {}
void printSts(int totalSteps){
/*for(int i=0; i<numNeighbors; i++){
CkPrintf("Elem[%d]: avg RTT from neighbor %d (actual elem id %d): %lf\n", thisIndex, i, neighbors[i], recvTimes[i]/totalSteps);
}*/
contribute(0,0,CkReduction::max_int);
}
void startInternalIteration() {
#if DEBUG
CkPrintf("[%d]: Start internal iteration \n", thisIndex);
#endif
neighborsRecved = 0;
#ifdef DOCOMP
//1: pick a work size and do some computation
int sum=0;
int N=curIterWorkSize;
for (int i=0; i<N; i++)
for (int j=0; j<N; j++)
for (int k=0; k<N; k++)
sum += (thisIndex*i+thisIndex*j+k)%WORKSIZECNT;
#endif
//2. send msg to K neighbors
int msgSize = curIterMsgSize;
//Send msgs to neighbors
for (int i=0; i<numNeighbors; i++) {
//double memtimer = CmiWallTimer();
#if REUSE_ITER_MSG
toNeighborMsg *msg = iterMsg[i];
#else
toNeighborMsg *msg = new(msgSize/4, 0) toNeighborMsg(msgSize/4);
#endif
#if DEBUG
CkPrintf("[%d]: send msg to neighbor[%d]=%d\n", thisIndex, i, neighbors[i]);
#endif
msg->setMsgSrc(thisIndex, i);
//double entrytimer = CmiWallTimer();
thisProxy(neighbors[i]).recvMsgs(msg);
//double entrylasttimer = CmiWallTimer();
//if(thisIndex==0){
// CkPrintf("At current step %d to neighbor %d, msg creation time: %f, entrymethod fire time: %f\n", internalStepCnt, neighbors[i], entrytimer-memtimer, entrylasttimer-entrytimer);
//}
}
}
void commWithNeighbors(int msgSize) {
internalStepCnt = 0;
curIterMsgSize = msgSize;
//currently the work size is only changed every big steps (which
//are initiated by the main proxy
curIterWorkSize = workSizeArr[random%WORKSIZECNT];
random++;
startTime = CmiWallTimer();
startInternalIteration();
}
void commWithNeighbors() {
internalStepCnt = 0;
curIterMsgSize = gMsgSize;
//currently the work size is only changed every big steps (which
//are initiated by the main proxy
curIterWorkSize = workSizeArr[random%WORKSIZECNT];
random++;
#if REUSE_ITER_MSG
if(iterMsg[0]==NULL){ //indicating the messages have not been created
for(int i=0; i<numNeighbors; i++)
iterMsg[i] = new(curIterMsgSize/4, 0) toNeighborMsg(curIterMsgSize/4);
}
#endif
startTime = CmiWallTimer();
startInternalIteration();
}
void recvReplies(toNeighborMsg *m) {
int fromNID = m->nID;
#if DEBUG
CkPrintf("[%d]: receive ack from neighbor[%d]=%d\n", thisIndex, fromNID, neighbors[fromNID]);
#endif
#if REUSE_ITER_MSG
iterMsg[fromNID] = m;
#else
delete m;
#endif
//recvTimes[fromNID] += (CmiWallTimer() - startTime);
//get one step time and send it back to mainProxy
neighborsRecved++;
if (neighborsRecved == numNeighbors) {
internalStepCnt++;
if (internalStepCnt==CALCPERSTEP) {
double iterCommTime = CmiWallTimer() - startTime;
#if USE_ARRAY_REDUCTION
contribute(sizeof(double), &iterCommTime, CkReduction::max_double);
#else
mainProxy.nextStep_plain(iterCommTime);
#endif
/*if(thisIndex==0){
for(int i=0; i<numNeighbors; i++){
CkPrintf("RTT time from neighbor %d (actual elem id %d): %lf\n", i, neighbors[i], recvTimes[i]);
}
}*/
} else {
startInternalIteration();
}
}
}
void recvMsgs(toNeighborMsg *m) {
#if DEBUG
CkPrintf("[%d]: recv msg from %d as its %dth neighbor\n", thisIndex, m->fromX, m->nID);
#endif
sum = m->sum();
thisProxy(m->fromX).recvReplies(m);
}
inline int MAX(int a, int b) {
return (a>b)?a:b;
}
inline int MIN(int a, int b) {
return (a<b)?a:b;
}
};
//int Block::workSizeArr[WORKSIZECNT] = {20, 60, 120, 180, 240};
int Block::workSizeArr[WORKSIZECNT] = {20};
#include "kNeighbor.def.h"
Attachment:
kNeighbor.ci
Description: Binary data
Attachment:
Makefile
Description: Binary data
- [charm] About syntax, SAGAR SHEDGE, 08/05/2011
- Re: [charm] [ppl] About syntax, Abhinav Bhatele, 08/05/2011
Archive powered by MHonArc 2.6.16.