00001 #include <map>
00002 #include "converse.h"
00003 #include "sockRoutines.h"
00004 #include "cklists.h"
00005
00006 #define DEBUGP(x)
00025 #if 1
00026
00027 #include <stdlib.h>
00028 #include <stdio.h>
00029 #include <unistd.h>
00030
00031 #include <stdlib.h>
00032 #include <stdio.h>
00033
00034 #if CMK_BLUEGENEL || CMK_BLUEGENEP || CMK_BLUEGENEQ
00035 #include "TopoManager.h"
00036 #endif
00037
00038 #if CMK_CRAYXT || CMK_CRAYXE
00039 extern "C" int getXTNodeID(int mpirank, int nummpiranks);
00040 #endif
00041
00042 #if defined(__APPLE__) && CMK_HAS_MULTIPROCESSING_H
00043 #include <Carbon/Carbon.h>
00044 #include <Multiprocessing.h>
00045 #endif
00046
00047 #if CMK_BIGSIM_CHARM
00048 #include "middle-blue.h"
00049 using namespace BGConverse;
00050 #endif
00051
00052 extern "C" int CmiNumCores(void) {
00053 int a = 1;
00054 #ifdef _WIN32
00055 struct _SYSTEM_INFO sysinfo;
00056 #endif
00057
00058
00059
00060 char *forcecount = getenv("FORCECPUCOUNT");
00061 if (forcecount != NULL) {
00062 if (sscanf(forcecount, "%d", &a) == 1) {
00063 return a;
00064 } else {
00065 a = 1;
00066 }
00067 }
00068
00069 #if defined(__APPLE__) && CMK_HAS_MULTIPROCESSING_H
00070 a = MPProcessorsScheduled();
00071 #endif
00072
00073 #ifdef _WIN32
00074
00075 GetSystemInfo(&sysinfo);
00076 a = sysinfo.dwNumberOfProcessors;
00077 #endif
00078
00079
00080 #ifdef _SC_NPROCESSORS_ONLN
00081 a = sysconf(_SC_NPROCESSORS_ONLN);
00082 #elif defined(_SC_CRAY_NCPU)
00083 a = sysconf(_SC_CRAY_NCPU);
00084 #elif defined(_SC_NPROC_ONLN)
00085 a = sysconf(_SC_NPROC_ONLN);
00086 #endif
00087 if (a == -1) a = 1;
00088
00089 #if defined(ARCH_HPUX11) || defined(ARCH_HPUX10)
00090 a = mpctl(MPC_GETNUMSPUS, 0, 0);
00091 #endif
00092
00093 return a;
00094 }
00095
00096 static int cpuTopoHandlerIdx;
00097 static int cpuTopoRecvHandlerIdx;
00098
00099 struct _procInfo {
00100 skt_ip_t ip;
00101 int pe;
00102 int ncores;
00103 int rank;
00104 int nodeID;
00105 };
00106
00107 typedef struct _hostnameMsg {
00108 char core[CmiMsgHeaderSizeBytes];
00109 int n;
00110 _procInfo *procs;
00111 } hostnameMsg;
00112
00113 typedef struct _nodeTopoMsg {
00114 char core[CmiMsgHeaderSizeBytes];
00115 int *nodes;
00116 } nodeTopoMsg;
00117
00118 static nodeTopoMsg *topomsg = NULL;
00119 static CmmTable hostTable;
00120
00121
00122 class CpuTopology {
00123 public:
00124 static int *nodeIDs;
00125 static int numPes;
00126 static int numNodes;
00127 static CkVec<int> *bynodes;
00128 static int supported;
00129
00130
00131 int numUniqNodes() {
00132 #if 0
00133 if (numNodes != 0) return numNodes;
00134 int n = 0;
00135 for (int i=0; i<CmiNumPes(); i++)
00136 if (nodeIDs[i] > n)
00137 n = nodeIDs[i];
00138 numNodes = n+1;
00139 return numNodes;
00140 #else
00141 if (numNodes > 0) return numNodes;
00142 CkVec<int> unodes;
00143 int i;
00144 for (i=0; i<numPes; i++) unodes.push_back(nodeIDs[i]);
00145
00146 unodes.quickSort();
00147 int last = -1;
00148 std::map<int, int> nodemap;
00149 for (i=0; i<numPes; i++) {
00150 if (unodes[i] != last) {
00151 last=unodes[i];
00152 nodemap[unodes[i]] = numNodes;
00153 numNodes++;
00154 }
00155 }
00156 if (numNodes == 0) {
00157 numNodes = CmiNumNodes();
00158 numPes = CmiNumPes();
00159 }
00160 else {
00161
00162 for (i=0; i<numPes; i++) nodeIDs[i] = nodemap[nodeIDs[i]];
00163 CpuTopology::supported = 1;
00164 }
00165 return numNodes;
00166 #endif
00167 }
00168
00169 void sort() {
00170 int i;
00171 numUniqNodes();
00172 bynodes = new CkVec<int>[numNodes];
00173 if (supported) {
00174 for (i=0; i<numPes; i++){
00175 CmiAssert(nodeIDs[i] >=0 && nodeIDs[i] <= numNodes);
00176 bynodes[nodeIDs[i]].push_back(i);
00177 }
00178 }
00179 else {
00180 for (i=0;i<CmiNumPes();i++) bynodes[CmiNodeOf(i)].push_back(i);
00181 }
00182 }
00183
00184 void print() {
00185 int i;
00186 CmiPrintf("Charm++> Cpu topology info:\n");
00187 CmiPrintf("PE to node map: ");
00188 for (i=0; i<CmiNumPes(); i++)
00189 CmiPrintf("%d ", nodeIDs[i]);
00190 CmiPrintf("\n");
00191 CmiPrintf("Node to PE map:\n");
00192 for (i=0; i<numNodes; i++) {
00193 CmiPrintf("Chip #%d: ", i);
00194 for (int j=0; j<bynodes[i].size(); j++)
00195 CmiPrintf("%d ", bynodes[i][j]);
00196 CmiPrintf("\n");
00197 }
00198 }
00199
00200 };
00201
00202 int *CpuTopology::nodeIDs = NULL;
00203 int CpuTopology::numPes = 0;
00204 int CpuTopology::numNodes = 0;
00205 CkVec<int> *CpuTopology::bynodes = NULL;
00206 int CpuTopology::supported = 0;
00207
00208 static CpuTopology cpuTopo;
00209 static CmiNodeLock topoLock = 0;
00210 static int done = 0;
00211
00212
00213 static void cpuTopoHandler(void *m)
00214 {
00215 _procInfo *rec;
00216 hostnameMsg *msg = (hostnameMsg *)m;
00217 char str[256];
00218 int tag, tag1, pe;
00219
00220 if (topomsg == NULL) {
00221 int i;
00222 hostTable = CmmNew();
00223 topomsg = (nodeTopoMsg *)CmiAlloc(sizeof(nodeTopoMsg)+CmiNumPes()*sizeof(int));
00224 CmiSetHandler((char *)topomsg, cpuTopoRecvHandlerIdx);
00225 topomsg->nodes = (int *)((char*)topomsg + sizeof(nodeTopoMsg));
00226 for (i=0; i<CmiNumPes(); i++) topomsg->nodes[i] = -1;
00227 }
00228 CmiAssert(topomsg != NULL);
00229
00230 msg->procs = (_procInfo*)((char*)msg + sizeof(hostnameMsg));
00231 CmiAssert(msg->n == CmiNumPes());
00232 for (int i=0; i<msg->n; i++)
00233 {
00234 _procInfo *proc = msg->procs+i;
00235
00236
00237
00238
00239
00240 tag = *(int*)&proc->ip;
00241 pe = proc->pe;
00242 if ((rec = (_procInfo *)CmmProbe(hostTable, 1, &tag, &tag1)) != NULL) {
00243 }
00244 else {
00245 proc->nodeID = pe;
00246 rec = proc;
00247 CmmPut(hostTable, 1, &tag, proc);
00248 }
00249 topomsg->nodes[pe] = rec->nodeID;
00250 rec->rank ++;
00251 }
00252
00253
00254 int ncores = CmiNumCores();
00255 if (ncores > 1)
00256 sprintf(str, "Charm++> Running on %d unique compute nodes (%d-way SMP).\n", CmmEntries(hostTable), ncores);
00257 else
00258 sprintf(str, "Charm++> Running on %d unique compute nodes.\n", CmmEntries(hostTable));
00259 CmiPrintf(str);
00260
00261 hostnameMsg *tmpm;
00262 tag = CmmWildCard;
00263 while (tmpm = (hostnameMsg *)CmmGet(hostTable, 1, &tag, &tag1));
00264 CmmFree(hostTable);
00265 CmiFree(msg);
00266
00267 CmiSyncBroadcastAllAndFree(sizeof(nodeTopoMsg)+CmiNumPes()*sizeof(int), (char *)topomsg);
00268 }
00269
00270
00271 static void cpuTopoRecvHandler(void *msg)
00272 {
00273 nodeTopoMsg *m = (nodeTopoMsg *)msg;
00274 m->nodes = (int *)((char*)m + sizeof(nodeTopoMsg));
00275
00276 CmiLock(topoLock);
00277 if (cpuTopo.nodeIDs == NULL) {
00278 cpuTopo.nodeIDs = m->nodes;
00279 cpuTopo.sort();
00280 }
00281 else
00282 CmiFree(m);
00283 done++;
00284 CmiUnlock(topoLock);
00285
00286
00287 }
00288
00289
00290 static void * combineMessage(int *size, void *data, void **remote, int count)
00291 {
00292 int i, j;
00293 int nprocs = ((hostnameMsg *)data)->n;
00294 if (count == 0) return data;
00295 for (i=0; i<count; i++) nprocs += ((hostnameMsg *)remote[i])->n;
00296 *size = sizeof(hostnameMsg)+sizeof(_procInfo)*nprocs;
00297 hostnameMsg *msg = (hostnameMsg *)CmiAlloc(*size);
00298 msg->procs = (_procInfo*)((char*)msg + sizeof(hostnameMsg));
00299 msg->n = nprocs;
00300 CmiSetHandler((char *)msg, cpuTopoHandlerIdx);
00301
00302 int n=0;
00303 hostnameMsg *m = (hostnameMsg*)data;
00304 m->procs = (_procInfo*)((char*)m + sizeof(hostnameMsg));
00305 for (j=0; j<m->n; j++)
00306 msg->procs[n++] = m->procs[j];
00307 for (i=0; i<count; i++) {
00308 m = (hostnameMsg*)remote[i];
00309 m->procs = (_procInfo*)((char*)m + sizeof(hostnameMsg));
00310 for (j=0; j<m->n; j++)
00311 msg->procs[n++] = m->procs[j];
00312 }
00313 return msg;
00314 }
00315
00316
00317
00318 extern "C" int LrtsCpuTopoEnabled()
00319 {
00320 return CpuTopology::supported;
00321 }
00322
00323 extern "C" int LrtsPeOnSameNode(int pe1, int pe2)
00324 {
00325 int *nodeIDs = cpuTopo.nodeIDs;
00326 if (!cpuTopo.supported || nodeIDs == NULL) return CmiNodeOf(pe1) == CmiNodeOf(pe2);
00327 else return nodeIDs[pe1] == nodeIDs[pe2];
00328 }
00329
00330
00331 extern "C" int LrtsNumNodes()
00332 {
00333 if (!cpuTopo.supported) return CmiNumNodes();
00334 else return cpuTopo.numUniqNodes();
00335 }
00336
00337 extern "C" int LrtsNodeSize(int node)
00338 {
00339 return !cpuTopo.supported?CmiNodeSize(node):(int)cpuTopo.bynodes[node].size();
00340 }
00341
00342
00343 extern "C" void LrtsPeOnNode(int node, int **pelist, int *num)
00344 {
00345 *num = cpuTopo.bynodes[node].size();
00346 if (pelist!=NULL && *num>0) *pelist = cpuTopo.bynodes[node].getVec();
00347 }
00348
00349 extern "C" int LrtsRankOf(int pe)
00350 {
00351 if (!cpuTopo.supported) return CmiRankOf(pe);
00352 const CkVec<int> &v = cpuTopo.bynodes[cpuTopo.nodeIDs[pe]];
00353 int rank = 0;
00354 int npes = v.size();
00355 while (rank < npes && v[rank] < pe) rank++;
00356 CmiAssert(v[rank] == pe);
00357 return rank;
00358 }
00359
00360 extern "C" int LrtsNodeOf(int pe)
00361 {
00362 if (!cpuTopo.supported) return CmiNodeOf(pe);
00363 return cpuTopo.nodeIDs[pe];
00364 }
00365
00366
00367 extern "C" int LrtsNodeFirst(int node)
00368 {
00369 if (!cpuTopo.supported) return CmiNodeFirst(node);
00370 return cpuTopo.bynodes[node][0];
00371 }
00372
00373
00374 static int _noip = 0;
00375 extern "C" void LrtsInitCpuTopo(char **argv)
00376 {
00377 static skt_ip_t myip;
00378 hostnameMsg *msg;
00379 double startT;
00380
00381 int obtain_flag = 1;
00382 int show_flag = 0;
00383
00384 if (CmiMyRank() ==0) {
00385 topoLock = CmiCreateLock();
00386 }
00387
00388 #if __FAULT__
00389 obtain_flag = 0;
00390 #endif
00391 if(CmiGetArgFlagDesc(argv,"+obtain_cpu_topology",
00392 "obtain cpu topology info"))
00393 obtain_flag = 1;
00394 if (CmiGetArgFlagDesc(argv,"+skip_cpu_topology",
00395 "skip the processof getting cpu topology info"))
00396 obtain_flag = 0;
00397 if(CmiGetArgFlagDesc(argv,"+show_cpu_topology",
00398 "Show cpu topology info"))
00399 show_flag = 1;
00400
00401 #if CMK_BIGSIM_CHARM
00402 if (BgNodeRank() == 0)
00403 #endif
00404 {
00405 cpuTopoHandlerIdx =
00406 CmiRegisterHandler((CmiHandler)cpuTopoHandler);
00407 cpuTopoRecvHandlerIdx =
00408 CmiRegisterHandler((CmiHandler)cpuTopoRecvHandler);
00409 }
00410
00411 if (!obtain_flag) {
00412 if (CmiMyRank() == 0) cpuTopo.sort();
00413 CmiNodeAllBarrier();
00414 CcdRaiseCondition(CcdTOPOLOGY_AVAIL);
00415 return;
00416 }
00417
00418 if (CmiMyPe() == 0) {
00419 #if CMK_BIGSIM_CHARM
00420 if (BgNodeRank() == 0)
00421 #endif
00422 startT = CmiWallTimer();
00423 }
00424
00425 #if CMK_BIGSIM_CHARM
00426 if (BgNodeRank() == 0)
00427 {
00428
00429 int numPes = cpuTopo.numPes = CkNumPes();
00430 cpuTopo.nodeIDs = new int[numPes];
00431 CpuTopology::supported = 1;
00432 int wth = BgGetNumWorkThread();
00433 for (int i=0; i<numPes; i++) {
00434 int nid = i / wth;
00435 cpuTopo.nodeIDs[i] = nid;
00436 }
00437 cpuTopo.sort();
00438 }
00439 return;
00440 #else
00441
00442 #if CMK_USE_GM
00443 CmiBarrier();
00444 #endif
00445
00446
00447 #if 0
00448 if (gethostname(hostname, 999)!=0) {
00449 strcpy(hostname, "");
00450 }
00451 #endif
00452 #if CMK_BLUEGENEL || CMK_BLUEGENEP
00453 if (CmiMyRank() == 0) {
00454 TopoManager tmgr;
00455
00456 int numPes = cpuTopo.numPes = CmiNumPes();
00457 cpuTopo.nodeIDs = new int[numPes];
00458 CpuTopology::supported = 1;
00459
00460 int x, y, z, t, nid;
00461 for(int i=0; i<numPes; i++) {
00462 tmgr.rankToCoordinates(i, x, y, z, t);
00463 nid = tmgr.coordinatesToRank(x, y, z, 0);
00464 cpuTopo.nodeIDs[i] = nid;
00465 }
00466 cpuTopo.sort();
00467 if (CmiMyPe()==0) CmiPrintf("Charm++> Running on %d unique compute nodes (%d-way SMP).\n", cpuTopo.numNodes, CmiNumCores());
00468 }
00469 CmiNodeAllBarrier();
00470 #elif CMK_BLUEGENEQ
00471 if (CmiMyRank() == 0) {
00472 TopoManager tmgr;
00473
00474 int numPes = cpuTopo.numPes = CmiNumPes();
00475 cpuTopo.nodeIDs = new int[numPes];
00476 CpuTopology::supported = 1;
00477
00478 int a, b, c, d, e, t, nid;
00479 for(int i=0; i<numPes; i++) {
00480 tmgr.rankToCoordinates(i, a, b, c, d, e, t);
00481 nid = tmgr.coordinatesToRank(a, b, c, d, e, 0);
00482 cpuTopo.nodeIDs[i] = nid;
00483 }
00484 cpuTopo.sort();
00485 if (CmiMyPe()==0) CmiPrintf("Charm++> Running on %d unique compute nodes (%d-way SMP).\n", cpuTopo.numNodes, CmiNumCores());
00486 }
00487 CmiNodeAllBarrier();
00488 #elif CMK_CRAYXT || CMK_CRAYXE
00489 if(CmiMyRank() == 0) {
00490 int numPes = cpuTopo.numPes = CmiNumPes();
00491 int numNodes = CmiNumNodes();
00492 cpuTopo.nodeIDs = new int[numPes];
00493 CpuTopology::supported = 1;
00494
00495 int nid;
00496 for(int i=0; i<numPes; i++) {
00497 nid = getXTNodeID(CmiNodeOf(i), numNodes);
00498 cpuTopo.nodeIDs[i] = nid;
00499 }
00500 int prev = -1;
00501 nid = -1;
00502
00503
00504
00505 for(int i=0; i<numPes; i++) {
00506 if(cpuTopo.nodeIDs[i] != prev) {
00507 prev = cpuTopo.nodeIDs[i];
00508 cpuTopo.nodeIDs[i] = ++nid;
00509 }
00510 else
00511 cpuTopo.nodeIDs[i] = nid;
00512 }
00513 cpuTopo.sort();
00514 if (CmiMyPe()==0) CmiPrintf("Charm++> Running on %d unique compute nodes (%d-way SMP).\n", cpuTopo.numNodes, CmiNumCores());
00515 }
00516 CmiNodeAllBarrier();
00517
00518 #else
00519
00520 if (CmiMyPe() >= CmiNumPes()) {
00521 CmiNodeAllBarrier();
00522 #if CMK_MACHINE_PROGRESS_DEFINED
00523 #if ! CMK_CRAYXT
00524 while (done < CmiMyNodeSize()) CmiNetworkProgress();
00525 #endif
00526 #endif
00527 return;
00528 }
00529
00530
00531 if (CmiMyRank() == 0)
00532 {
00533 #if CMK_HAS_GETHOSTNAME && !CMK_BLUEGENEQ
00534 myip = skt_my_ip();
00535
00536 #elif CMK_BPROC
00537 myip = skt_innode_my_ip();
00538 #else
00539 if (!CmiMyPe())
00540 CmiPrintf("CmiInitCPUTopology Warning: Can not get unique name for the compute nodes. \n");
00541 _noip = 1;
00542 #endif
00543 }
00544 cpuTopo.numPes = CmiNumPes();
00545
00546 CmiNodeAllBarrier();
00547 if (_noip) return;
00548
00549
00550 msg = (hostnameMsg *)CmiAlloc(sizeof(hostnameMsg)+sizeof(_procInfo));
00551 msg->n = 1;
00552 msg->procs = (_procInfo*)((char*)msg + sizeof(hostnameMsg));
00553 CmiSetHandler((char *)msg, cpuTopoHandlerIdx);
00554 msg->procs[0].pe = CmiMyPe();
00555 msg->procs[0].ip = myip;
00556 msg->procs[0].ncores = CmiNumCores();
00557 msg->procs[0].rank = 0;
00558 msg->procs[0].nodeID = 0;
00559 CmiReduce(msg, sizeof(hostnameMsg)+sizeof(_procInfo), combineMessage);
00560
00561
00562 while (done != CmiMyNodeSize())
00563 CsdSchedulePoll();
00564
00565 if (CmiMyPe() == 0) {
00566 #if CMK_BIGSIM_CHARM
00567 if (BgNodeRank() == 0)
00568 #endif
00569 CmiPrintf("Charm++> cpu topology info is gathered in %.3f seconds.\n", CmiWallTimer()-startT);
00570 }
00571 #endif
00572
00573 #endif
00574
00575
00576 CcdRaiseCondition(CcdTOPOLOGY_AVAIL);
00577 if (CmiMyPe() == 0 && show_flag) cpuTopo.print();
00578 }
00579
00580 #else
00581
00582 extern "C" void LrtsInitCpuTopo(char **argv)
00583 {
00584
00585 int obtain_flag = CmiGetArgFlagDesc(argv,"+obtain_cpu_topology",
00586 "obtain cpu topology info");
00587 CmiGetArgFlagDesc(argv,"+skip_cpu_topology",
00588 "skip the processof getting cpu topology info");
00589 CmiGetArgFlagDesc(argv,"+show_cpu_topology",
00590 "Show cpu topology info");
00591 }
00592
00593 #endif
00594
00595 extern "C" int CmiCpuTopologyEnabled()
00596 {
00597 return LrtsCpuTopoEnabled();
00598 }
00599 extern "C" int CmiPeOnSamePhysicalNode(int pe1, int pe2)
00600 {
00601 return LrtsPeOnSameNode(pe1, pe2);
00602 }
00603 extern "C" int CmiNumPhysicalNodes()
00604 {
00605 return LrtsNumNodes();
00606 }
00607 extern "C" int CmiNumPesOnPhysicalNode(int node)
00608 {
00609 return LrtsNodeSize(node);
00610 }
00611 extern "C" void CmiGetPesOnPhysicalNode(int node, int **pelist, int *num)
00612 {
00613 LrtsPeOnNode(node, pelist, num);
00614 }
00615 extern "C" int CmiPhysicalRank(int pe)
00616 {
00617 return LrtsRankOf(pe);
00618 }
00619 extern "C" int CmiPhysicalNodeID(int pe)
00620 {
00621 return LrtsNodeOf(pe);
00622 }
00623 extern "C" int CmiGetFirstPeOnPhysicalNode(int node)
00624 {
00625 return LrtsNodeFirst(node);
00626 }
00627 extern "C" void CmiInitCPUTopology(char **argv)
00628 {
00629 LrtsInitCpuTopo(argv);
00630 }
00631