Bug #1559: fixed cpuaffinity.c build errors
[charm.git] / src / conv-core / memoryaffinity.c
blob08570f2beb9d3f8e57aca600954dfce6e29e5928
1 /**
2 * Considering the effect of memory affinity on the performance
3 * for the NUMA nodes.
5 * Author: Christiane Pousa Ribeiro
6 * LIG - INRIA - MESCAL
7 * April, 2010
9 * Modified and integrated into Charm++ by Chao Mei
10 * May, 2010
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() {
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;
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;
88 closedir(nodeDir);
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
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 void CmiInitMemAffinity(char **argv) {
116 int i;
117 int policy=-1;
118 /*step1: parsing args maffinity, mempol and nodemap (nodemap is optional)*/
119 int maffinity_flag = CmiGetArgFlagDesc(argv, "+maffinity", "memory affinity");
120 /*the node here refers to the nodes that are seen by libnuma on a phy node*/
121 /*nodemap is a string of ints separated by ","*/
122 char *nodemap = NULL;
124 char *mpol = NULL;
125 CmiGetArgStringDesc(argv, "+memnodemap", &nodemap, "define memory node mapping");
126 CmiGetArgStringDesc(argv, "+mempol", &mpol, "define memory policy {bind, preferred or interleave} ");
129 if (!maffinity_flag) return;
131 /*Currently skip the communication thread*/
133 * Note: the cpu affinity of comm thread may not be set
134 * if "commap" is not specified. This is why the following
135 * code regarding the comm thd needs to be put before
136 * the codes that checks whether cpu affinity is set
137 * or not
139 if (CmiMyPe() >= CmiNumPes()) {
140 CmiNodeAllBarrier();
141 return;
144 /*step2: checking whether the required cpu affinity has been set*/
145 if (CpvInitialized(myCPUAffToCore) && CpvAccess(myCPUAffToCore)==-1) {
146 if (CmiMyPe()==0)
147 CmiPrintf("Charm++> memory affinity disabled because cpu affinity is not enabled!\n");
148 CmiNodeAllBarrier();
149 return;
152 if (CmiMyPe()==0) {
153 CmiPrintf("Charm++> memory affinity enabled! \n");
156 /*Select memory policy*/
157 if (mpol==NULL) {
158 CmiAbort("Memory policy must be specified!\n");
160 if (strcmp(mpol, "interleave")==0) policy = MPOL_INTERLEAVE;
161 else if (strcmp(mpol, "preferred")==0) policy = MPOL_PREFERRED;
162 else if (strcmp(mpol, "bind")==0) policy = MPOL_BIND;
163 else {
164 CmiPrintf("Error> Invalid memory policy :%s\n", mpol);
165 CmiAbort("Invalid memory policy!");
169 * step3: check whether nodemap is NULL or not
170 * step 3a): nodemap is not NULL
171 * step 3b): nodemap is NULL, set memory policy according to the result
172 * of cpu affinity settings.
174 if (nodemap!=NULL) {
175 int *nodemapArr = NULL;
176 int nodemapArrSize = 1;
177 int prevIntStart,j;
178 int curnid;
179 int myPhyRank = CpvAccess(myCPUAffToCore);
180 int myMemNid;
181 int retval = -1;
182 for (i=0; i<strlen((const char *)nodemap); i++) {
183 if (nodemap[i]==',') nodemapArrSize++;
185 nodemapArr = malloc(nodemapArrSize*sizeof(int));
186 prevIntStart=j=0;
187 for (i=0; i<strlen((const char *)nodemap); i++) {
188 if (nodemap[i]==',') {
189 curnid = atoi(nodemap+prevIntStart);
190 if (curnid >= CmiNumNUMANodes()) {
191 CmiPrintf("Error> Invalid node number %d, only have %d nodes (0-%d) on the machine. \n", curnid, CmiNumNUMANodes(), CmiNumNUMANodes()-1);
192 CmiAbort("Invalid node number!");
194 nodemapArr[j++] = curnid;
195 prevIntStart=i+1;
198 /*record the last nid after the last comma*/
199 curnid = atoi(nodemap+prevIntStart);
200 if (curnid >= CmiNumNUMANodes()) {
201 CmiPrintf("Error> Invalid node number %d, only have %d nodes (0-%d) on the machine. \n", curnid, CmiNumNUMANodes(), CmiNumNUMANodes()-1);
202 CmiAbort("Invalid node number!");
204 nodemapArr[j] = curnid;
206 myMemNid = nodemapArr[myPhyRank%nodemapArrSize];
207 if (policy==MPOL_INTERLEAVE) {
208 retval = CmiSetMemAffinity(policy, nodemapArr, nodemapArrSize);
209 } else {
210 retval = CmiSetMemAffinity(policy, &myMemNid, 1);
212 if (retval<0) {
213 CmiAbort("set_mempolicy error w/ mem nodemap");
215 free(nodemapArr);
216 } else {
217 /*use the affinity map set by the cpu affinity*/
218 int myPhyRank = CpvAccess(myCPUAffToCore);
219 /*get the NUMA node id from myPhyRank (a core id)*/
220 int myMemNid = getNUMANidByRank(myPhyRank);
222 int retval=-1;
223 if (policy==MPOL_INTERLEAVE) {
224 int totalNUMANodes = CmiNumNUMANodes();
225 int *nids = (int *)malloc(totalNUMANodes*sizeof(int));
226 for (i=0; i<totalNUMANodes; i++) nids[i] = i;
227 retval = CmiSetMemAffinity(policy, nids, totalNUMANodes);
228 free(nids);
229 } else {
230 retval = CmiSetMemAffinity(policy, &myMemNid, 1);
232 if (retval<0) {
233 CmiAbort("set_mempolicy error w/o mem nodemap");
237 /*print_mem_affinity();*/
238 CmiNodeAllBarrier();
240 #else
241 void CmiInitMemAffinity(char **argv) {
242 char *tmpstr = NULL;
243 int maffinity_flag = CmiGetArgFlagDesc(argv,"+maffinity",
244 "memory affinity");
245 if (maffinity_flag && CmiMyPe()==0)
246 CmiPrintf("memory affinity is not supported, +maffinity flag disabled.\n");
248 /* consume the remaining possible arguments */
249 CmiGetArgStringDesc(argv, "+memnodemap", &tmpstr, "define memory node mapping");
250 CmiGetArgStringDesc(argv, "+mempol", &tmpstr, "define memory policy {bind, preferred or interleave} ");
252 #endif