2 * Considering the effect of memory affinity on the performance
5 * Author: Christiane Pousa Ribeiro
9 * Modified and integrated into Charm++ by Chao Mei
14 #include "sockRoutines.h"
15 #define DEBUGP(x) /* CmiPrintf x; */
16 CpvExtern(int, myCPUAffToCore
);
22 #include <linux/mempolicy.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) {
42 unsigned int len
= 8*sizeof(mask
);
46 /* Memory policy to the current process */
47 if ((get_mempolicy(&policy
,&mask
,len
,0,0)) < 0) {
48 perror("mem_getaffinity");
51 if (policy
== MPOL_INTERLEAVE
)
52 strcpy(spol
,"INTERLEAVE");
53 else if (policy
== MPOL_BIND
)
56 strcpy(spol
,"PREFERRED");
57 CmiPrintf("%d: Mem affinity mask is: %08lx with policy %s\n", CmiMyPe(),mask
,spol
);
60 static int CmiNumNUMANodes(void) {
61 return numa_max_node()+1;
63 static int getNUMANidByRank(int coreid
) {
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);*/
74 struct dirent
* nodeDirEnt
;
76 for (i
=0; i
<totalNUMANodes
; i
++) {
77 snprintf(nodeStr
, 256, "/sys/devices/system/node/node%d", i
);
78 nodeDir
= opendir(nodeStr
);
80 while ((nodeDirEnt
= readdir(nodeDir
))) {
81 if (sscanf(nodeDirEnt
->d_name
, "cpu%d", &cpuid
) == 1) {
92 CmiPrintf("%d: the corresponding NUMA node for cpu id %d is not found!\n", CmiMyPe(), coreid
);
98 * policy: indicates the memory policy
99 * nids: indicates the NUMA nodes to be applied
100 * len: indicates how many NUMA nodes nids has
102 int CmiSetMemAffinity(int policy
, int *nids
, int len
) {
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
);
115 void CmiInitMemAffinity(char **argv
) {
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
;
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*/
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
140 if (CmiMyPe() >= CmiNumPes()) {
145 /*step2: checking whether the required cpu affinity has been set*/
146 if (CpvInitialized(myCPUAffToCore
) && CpvAccess(myCPUAffToCore
)==-1) {
148 CmiPrintf("Charm++> memory affinity disabled because cpu affinity is not enabled!\n");
154 CmiPrintf("Charm++> memory affinity enabled! \n");
157 /*Select memory policy*/
159 CmiAbort("Memory policy must be specified!\n");
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
;
165 CmiPrintf("Error> Invalid memory policy :%s\n", mpol
);
166 CmiAbort("Invalid memory policy!");
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.
176 int *nodemapArr
= NULL
;
177 int nodemapArrSize
= 1;
180 int myPhyRank
= CpvAccess(myCPUAffToCore
);
183 for (i
=0; i
<strlen((const char *)nodemap
); i
++) {
184 if (nodemap
[i
]==',') nodemapArrSize
++;
186 nodemapArr
= malloc(nodemapArrSize
*sizeof(int));
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!");
195 nodemapArr
[j
++] = curnid
;
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!");
205 nodemapArr
[j
] = curnid
;
207 myMemNid
= nodemapArr
[myPhyRank
%nodemapArrSize
];
208 if (policy
==MPOL_INTERLEAVE
) {
209 retval
= CmiSetMemAffinity(policy
, nodemapArr
, nodemapArrSize
);
211 retval
= CmiSetMemAffinity(policy
, &myMemNid
, 1);
214 CmiAbort("set_mempolicy error w/ mem nodemap");
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
);
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
);
231 retval
= CmiSetMemAffinity(policy
, &myMemNid
, 1);
234 CmiAbort("set_mempolicy error w/o mem nodemap");
238 /*print_mem_affinity();*/
243 void CmiInitMemAffinity(char **argv
) {
245 int maffinity_flag
= CmiGetArgFlagDesc(argv
,"+maffinity",
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} ");