Rename the majority of remaining C files in the RTS to C++
[charm.git] / src / conv-core / memoryaffinity.C
blobeb4d8f9754cacb1442b6551b39eb5bba75b23c84
1 /**
2   * Considering the effect of memory affinity on the performance
3   * for the NUMA nodes.
4   *
5   * Author: Christiane Pousa Ribeiro
6   * LIG - INRIA - MESCAL
7   * April, 2010
8   *
9   * Modified and integrated into Charm++ by Chao Mei
10   * May, 2010
11   */
13 #include "converse.h"
14 #include "sockRoutines.h"
15 #define DEBUGP(x)  /* CmiPrintf x;  */
16 CpvExtern(int, myCPUAffToCore);
17 #if CMK_HAS_NUMACTRL
18 #define _GNU_SOURCE
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <unistd.h>
22 #include <linux/mempolicy.h>
23 #include <numaif.h>
24 #include <numa.h>
25 #include <string.h>
26 #include <sched.h>
27 #include <math.h>
28 #include <dirent.h>
29 #include <sys/types.h>
30 typedef unsigned long mem_aff_mask;
31 static void MEM_MASK_ZERO(mem_aff_mask *mem_mask) {
32     memset(mem_mask, 0, sizeof(mem_aff_mask));
34 static void MEM_MASK_SET(int nid, mem_aff_mask *mem_mask) {
35     *mem_mask = *mem_mask | (1<<nid);
37 static void MEM_MASK_CLEAR(int nid, mem_aff_mask *mem_mask) {
38     *mem_mask = *mem_mask & (~(1<<nid));
40 int print_mem_affinity(void) {
41     mem_aff_mask mask;
42     unsigned int len = 8*sizeof(mask);
43     char spol[16];
44     int policy;
45     spol[0]='\0';
46     /* Memory policy to the current process */
47     if ((get_mempolicy(&policy,&mask,len,0,0)) < 0) {
48         perror("mem_getaffinity");
49         return -1;
50     }
51     if (policy == MPOL_INTERLEAVE)
52         strcpy(spol,"INTERLEAVE");
53     else if (policy == MPOL_BIND)
54         strcpy(spol,"BIND");
55     else
56         strcpy(spol,"PREFERRED");
57     CmiPrintf("%d: Mem affinity mask is: %08lx with policy %s\n", CmiMyPe(),mask,spol);
58     return 0;
60 static int CmiNumNUMANodes(void) {
61     return numa_max_node()+1;
63 static int getNUMANidByRank(int coreid) {
64     int i;
65     /*int totalCores = CmiNumCores();*/
66     int totalNUMANodes = CmiNumNUMANodes();
67     /*The core id array is viewed as 2D array but in form of 1D array*/
68     /*int *coreids=(int *)malloc(sizeof(int)*totalCores);*/
69     /*Assume each NUMA node has the same number of cores*/
70     /*int nCoresPerNode = totalCores/totalNUMANodes;*/
71     /*CmiAssert(totalCores%totalNUMANodes==0);*/
72     char nodeStr[256];
73     DIR* nodeDir;
74     struct dirent* nodeDirEnt;
75     int cpuid = -1;
76     for (i=0; i<totalNUMANodes; i++) {
77         snprintf(nodeStr, 256, "/sys/devices/system/node/node%d", i);
78         nodeDir = opendir(nodeStr);
79         if (nodeDir) {
80             while ((nodeDirEnt = readdir(nodeDir))) {
81                 if (sscanf(nodeDirEnt->d_name, "cpu%d", &cpuid) == 1) {
82                     if(cpuid == coreid) {
83                         closedir(nodeDir);
84                         return i;
85                     }
86                 }
87             }
88             closedir(nodeDir);
89         }
90     }
91     /*free(coreids);*/
92     CmiPrintf("%d: the corresponding NUMA node for cpu id %d is not found!\n", CmiMyPe(), coreid);
93     CmiAssert(0);
94     return -1;
97 /**
98  * policy: indicates the memory policy
99  * nids: indicates the NUMA nodes to be applied
100  * len: indicates how many NUMA nodes nids has
101  */
102 int CmiSetMemAffinity(int policy, int *nids, int len) {
103     int i;
104     mem_aff_mask myMask;
105     unsigned int masksize = 8*sizeof(mem_aff_mask);
106     MEM_MASK_ZERO(&myMask);
107     for (i=0; i<len; i++) MEM_MASK_SET(nids[i], &myMask);
108     if (set_mempolicy(policy, &myMask, masksize)<0) {
109         CmiPrintf("Error> setting memory policy (%d) error with mask %X\n", policy, myMask);
110         return -1;
111     } else
112         return 0;
114 CMI_EXTERNC
115 void CmiInitMemAffinity(char **argv) {
117     int i;
118     int policy=-1;
119     /*step1: parsing args maffinity, mempol and nodemap (nodemap is optional)*/
120     int maffinity_flag = CmiGetArgFlagDesc(argv, "+maffinity", "memory affinity");
121     /*the node here refers to the nodes that are seen by libnuma on a phy node*/
122     /*nodemap is a string of ints separated by ","*/
123     char *nodemap = NULL;
125     char *mpol = NULL;
126     CmiGetArgStringDesc(argv, "+memnodemap", &nodemap, "define memory node mapping");
127     CmiGetArgStringDesc(argv, "+mempol", &mpol, "define memory policy {bind, preferred or interleave} ");
130     if (!maffinity_flag) return;
132     /*Currently skip the communication thread*/
133     /**
134       * Note: the cpu affinity of comm thread may not be set
135       * if "commap" is not specified. This is why the following
136       * code regarding the comm thd needs to be put before
137       * the codes that checks whether cpu affinity is set
138       * or not
139       */
140     if (CmiMyPe() >= CmiNumPes()) {
141         CmiNodeAllBarrier();
142         return;
143     }
145     /*step2: checking whether the required cpu affinity has been set*/
146     if (CpvInitialized(myCPUAffToCore) && CpvAccess(myCPUAffToCore)==-1) {
147         if (CmiMyPe()==0)
148             CmiPrintf("Charm++> memory affinity disabled because cpu affinity is not enabled!\n");
149         CmiNodeAllBarrier();
150         return;
151     }
153     if (CmiMyPe()==0) {
154         CmiPrintf("Charm++> memory affinity enabled! \n");
155     }
157     /*Select memory policy*/
158     if (mpol==NULL) {
159         CmiAbort("Memory policy must be specified!\n");
160     }
161     if (strcmp(mpol, "interleave")==0) policy = MPOL_INTERLEAVE;
162     else if (strcmp(mpol, "preferred")==0) policy = MPOL_PREFERRED;
163     else if (strcmp(mpol, "bind")==0) policy = MPOL_BIND;
164     else {
165         CmiPrintf("Error> Invalid memory policy :%s\n", mpol);
166         CmiAbort("Invalid memory policy!");
167     }
169     /**
170      * step3: check whether nodemap is NULL or not
171      * step 3a): nodemap is not NULL
172      * step 3b): nodemap is NULL, set memory policy according to the result
173      * of cpu affinity settings.
174      */
175     if (nodemap!=NULL) {
176         int *nodemapArr = NULL;
177         int nodemapArrSize = 1;
178         int prevIntStart,j;
179         int curnid;
180         int myPhyRank = CpvAccess(myCPUAffToCore);
181         int myMemNid;
182         int retval = -1;
183         for (i=0; i<strlen((const char *)nodemap); i++) {
184             if (nodemap[i]==',') nodemapArrSize++;
185         }
186         nodemapArr = malloc(nodemapArrSize*sizeof(int));
187         prevIntStart=j=0;
188         for (i=0; i<strlen((const char *)nodemap); i++) {
189             if (nodemap[i]==',') {
190                 curnid = atoi(nodemap+prevIntStart);
191                 if (curnid >= CmiNumNUMANodes()) {
192                     CmiPrintf("Error> Invalid node number %d, only have %d nodes (0-%d) on the machine. \n", curnid, CmiNumNUMANodes(), CmiNumNUMANodes()-1);
193                     CmiAbort("Invalid node number!");
194                 }
195                 nodemapArr[j++] = curnid;
196                 prevIntStart=i+1;
197             }
198         }
199         /*record the last nid after the last comma*/
200         curnid = atoi(nodemap+prevIntStart);
201         if (curnid >= CmiNumNUMANodes()) {
202             CmiPrintf("Error> Invalid node number %d, only have %d nodes (0-%d) on the machine. \n", curnid, CmiNumNUMANodes(), CmiNumNUMANodes()-1);
203             CmiAbort("Invalid node number!");
204         }
205         nodemapArr[j] = curnid;
207         myMemNid = nodemapArr[myPhyRank%nodemapArrSize];
208         if (policy==MPOL_INTERLEAVE) {
209             retval = CmiSetMemAffinity(policy, nodemapArr, nodemapArrSize);
210         } else {
211             retval = CmiSetMemAffinity(policy, &myMemNid, 1);
212         }
213         if (retval<0) {
214             CmiAbort("set_mempolicy error w/ mem nodemap");
215         }
216         free(nodemapArr);
217     } else {
218         /*use the affinity map set by the cpu affinity*/
219         int myPhyRank = CpvAccess(myCPUAffToCore);
220         /*get the NUMA node id from myPhyRank (a core id)*/
221         int myMemNid = getNUMANidByRank(myPhyRank);
223         int retval=-1;
224         if (policy==MPOL_INTERLEAVE) {
225             int totalNUMANodes = CmiNumNUMANodes();
226             int *nids = (int *)malloc(totalNUMANodes*sizeof(int));
227             for (i=0; i<totalNUMANodes; i++) nids[i] = i;
228             retval = CmiSetMemAffinity(policy, nids, totalNUMANodes);
229             free(nids);
230         } else {
231             retval = CmiSetMemAffinity(policy, &myMemNid, 1);
232         }
233         if (retval<0) {
234             CmiAbort("set_mempolicy error w/o mem nodemap");
235         }
236     }
238     /*print_mem_affinity();*/
239     CmiNodeAllBarrier();
241 #else
242 CMI_EXTERNC
243 void CmiInitMemAffinity(char **argv) {
244     char *tmpstr = NULL;
245     int maffinity_flag = CmiGetArgFlagDesc(argv,"+maffinity",
246                                            "memory affinity");
247     if (maffinity_flag && CmiMyPe()==0)
248         CmiPrintf("memory affinity is not supported, +maffinity flag disabled.\n");
250     /* consume the remaining possible arguments */
251     CmiGetArgStringDesc(argv, "+memnodemap", &tmpstr, "define memory node mapping");
252     CmiGetArgStringDesc(argv, "+mempol", &tmpstr, "define memory policy {bind, preferred or interleave} ");
254 #endif