summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--c2python/pmmodule.c342
1 files changed, 342 insertions, 0 deletions
diff --git a/c2python/pmmodule.c b/c2python/pmmodule.c
new file mode 100644
index 0000000..3cd404d
--- /dev/null
+++ b/c2python/pmmodule.c
@@ -0,0 +1,342 @@
1/*
2 * pmmodule.c
3 *
4 * C module to access pm data (preemption and migration ovd and length)
5 * from python.
6 *
7 * The rationale is to process the bulk of a sample set using C, then
8 * move only the interesting values to Python.
9 */
10#include <Python.h>
11#include <numpy/arrayobject.h>
12
13#include "pm_common.h"
14
15static struct ovd_plen *preempt = NULL;
16static struct ovd_plen *samel2 = NULL;
17static struct ovd_plen *samechip = NULL;
18static struct ovd_plen *offchip = NULL;
19
20static int pcount = 0;
21static int l2count = 0;
22static int chipcount = 0;
23static int offcount = 0;
24
25static int loaded(int set)
26{
27 static int load = 0;
28 if(!load && set)
29 load = 1;
30
31 return load;
32}
33
34static void cleanup()
35{
36 free(preempt);
37 if(samel2)
38 free(samel2);
39 free(samechip);
40 free(offchip);
41}
42
43/*
44 * pm_load: load raw data from filename and process overheads
45 * for hierarchy of up to L3 cache levels
46 *
47 * @filename: raw data file
48 * @cores_per_l2: number of cores that share an L2 cache
49 * if (cores_per_l2 == 0) then all cores in a chip share
50 * the L2 cache (i.e., no L3)
51 * @num_phys_cpu: number of physical sockets
52 *
53 * TODO this should be (re)integrated at some point, to allow NUMA / other
54 * topologies evaluations
55 * @cores_per_chip: number of cores per chip (they can share a L3 or a L2
56 * cache. This is decided by the cores_per_l2 value)
57 */
58static PyObject* pm_load(PyObject *self, PyObject *args)
59{
60 const char *filename;
61 unsigned int cores_per_l2;
62 unsigned int num_phys_cpu;
63 int wss;
64 int tss;
65
66 struct full_ovd_plen *full_costs = NULL;
67 int num_samples;
68
69 if (!PyArg_ParseTuple(args, "sIIii", &filename, &cores_per_l2,
70 &num_phys_cpu, &wss, &tss))
71 return NULL;
72
73 /* get valid overheads from raw file */
74 if ((num_samples = get_valid_ovd(filename, &full_costs, wss, tss)) < 0)
75 goto err;
76
77 if ((preempt = malloc(num_samples * sizeof(struct ovd_plen))) < 0)
78 goto err;
79
80 memset(preempt, 0, num_samples * sizeof(struct ovd_plen));
81
82 if (cores_per_l2) {
83 if((samel2 = malloc(num_samples * sizeof(struct ovd_plen))) < 0)
84 goto err_samel2;
85
86 memset(samel2, 0, num_samples * sizeof(struct ovd_plen));
87 }
88
89 if((samechip = malloc(num_samples * sizeof(struct ovd_plen))) < 0)
90 goto err_samechip;
91
92 memset(samechip, 0, num_samples * sizeof(struct ovd_plen));
93
94 if((offchip = malloc(num_samples * sizeof(struct ovd_plen))) < 0)
95 goto err_offchip;
96
97 memset(offchip, 0, num_samples * sizeof(struct ovd_plen));
98
99 /* get p/m overheads and lengths */
100 get_ovd_plen_umaxeon(full_costs, num_samples, cores_per_l2, num_phys_cpu,
101 preempt, &pcount, samel2, &l2count, samechip, &chipcount,
102 offchip, &offcount);
103
104 loaded(1);
105
106 free(full_costs);
107 Py_INCREF(Py_None);
108 return Py_None;
109
110err_offchip:
111 free(samechip);
112err_samechip:
113 if(cores_per_l2)
114 free(samel2);
115err_samel2:
116 free(preempt);
117err:
118 free(full_costs);
119 PyErr_Format(PyExc_ValueError, "Cannot load / analyze raw data");
120 return NULL;
121}
122
123/* return the preemption (ovd, length) NumPy array with shape (pcount,2) */
124static PyObject* pm_get_preemption(PyObject *self, PyObject *args)
125{
126 PyArrayObject *py_preempt;
127 npy_intp shape[2];
128
129 int i;
130 long long *tmp;
131
132 if (!loaded(0)) {
133 PyErr_Format(PyExc_ValueError, "pm not Loaded!");
134 return NULL;
135 }
136
137 shape[0] = pcount;
138 shape[1] = 2;
139
140 if (!PyArg_ParseTuple(args,""))
141 return NULL;
142
143 py_preempt = (PyArrayObject *) PyArray_SimpleNew(2,shape,NPY_LONGLONG);
144 if (!py_preempt)
145 goto err_alloc;
146
147 for (i = 0; i < pcount; i++) {
148 tmp = (long long *) PyArray_GETPTR2(py_preempt, i, 0);
149 if(!tmp)
150 goto err;
151
152 *tmp = (long long) preempt[i].ovd;
153
154 tmp = (long long *) PyArray_GETPTR2(py_preempt, i, 1);
155 if(!tmp)
156 goto err;
157
158 *tmp = (long long) preempt[i].plen;
159 }
160
161 free(preempt);
162 return (PyObject *) py_preempt;
163
164err:
165 PyArray_free(py_preempt);
166err_alloc:
167 PyErr_Format(PyExc_ValueError, "pm_get_preemption Error");
168 cleanup();
169 return NULL;
170}
171
172/* return the samel2 (ovd, length) NumPy array with shape (l2count,2) */
173static PyObject* pm_get_samel2(PyObject *self, PyObject *args)
174{
175 PyArrayObject *py_samel2;
176 npy_intp shape[2];
177
178 int i;
179 long long *tmp;
180
181 if (!loaded(0)) {
182 PyErr_Format(PyExc_ValueError, "pm not Loaded!");
183 return NULL;
184 }
185
186 shape[0] = l2count;
187 shape[1] = 2;
188
189 if (!PyArg_ParseTuple(args,""))
190 return NULL;
191
192 py_samel2 = (PyArrayObject *) PyArray_SimpleNew(2,shape,NPY_LONGLONG);
193 if (!py_samel2)
194 goto err_alloc;
195
196 for (i = 0; i < l2count; i++) {
197 tmp = (long long *) PyArray_GETPTR2(py_samel2, i, 0);
198 if(!tmp)
199 goto err;
200
201 *tmp = (long long) samel2[i].ovd;
202
203 tmp = (long long *) PyArray_GETPTR2(py_samel2, i, 1);
204 if(!tmp)
205 goto err;
206
207 *tmp = (long long) samel2[i].plen;
208 }
209
210 free(samel2);
211 return (PyObject *) py_samel2;
212
213err:
214 PyArray_free(py_samel2);
215err_alloc:
216 PyErr_Format(PyExc_ValueError, "pm_get_preemption Error");
217 cleanup();
218 return NULL;
219}
220
221/* return the samechip (ovd, length) NumPy array with shape (chipcount,2) */
222static PyObject* pm_get_samechip(PyObject *self, PyObject *args)
223{
224 PyArrayObject *py_samechip;
225 npy_intp shape[2];
226
227 int i;
228 long long *tmp;
229
230 if (!loaded(0)) {
231 PyErr_Format(PyExc_ValueError, "pm not Loaded!");
232 return NULL;
233 }
234
235 shape[0] = chipcount;
236 shape[1] = 2;
237
238 if (!PyArg_ParseTuple(args,""))
239 return NULL;
240
241 py_samechip = (PyArrayObject *) PyArray_SimpleNew(2,shape,NPY_LONGLONG);
242 if (!py_samechip)
243 goto err_alloc;
244
245 for (i = 0; i < chipcount; i++) {
246 tmp = (long long *) PyArray_GETPTR2(py_samechip, i, 0);
247 if(!tmp)
248 goto err;
249
250 *tmp = (long long) samechip[i].ovd;
251
252 tmp = (long long *) PyArray_GETPTR2(py_samechip, i, 1);
253 if(!tmp)
254 goto err;
255
256 *tmp = (long long) samechip[i].plen;
257 }
258
259 free(samechip);
260 return (PyObject *) py_samechip;
261
262err:
263 PyArray_free(py_samechip);
264err_alloc:
265 PyErr_Format(PyExc_ValueError, "pm_get_preemption Error");
266 cleanup();
267 return NULL;
268}
269
270/* return the offchip (ovd, length) NumPy array with shape (offcount,2) */
271static PyObject* pm_get_offchip(PyObject *self, PyObject *args)
272{
273 PyArrayObject *py_offchip;
274 npy_intp shape[2];
275
276 int i;
277 long long *tmp;
278
279 if (!loaded(0)) {
280 PyErr_Format(PyExc_ValueError, "pm not Loaded!");
281 return NULL;
282 }
283
284 shape[0] = offcount;
285 shape[1] = 2;
286
287 if (!PyArg_ParseTuple(args,""))
288 return NULL;
289
290 py_offchip = (PyArrayObject *) PyArray_SimpleNew(2,shape,NPY_LONGLONG);
291 if (!py_offchip)
292 goto err_alloc;
293
294 for (i = 0; i < offcount; i++) {
295 tmp = (long long *) PyArray_GETPTR2(py_offchip, i, 0);
296 if(!tmp)
297 goto err;
298
299 *tmp = (long long) offchip[i].ovd;
300
301 tmp = (long long *) PyArray_GETPTR2(py_offchip, i, 1);
302 if(!tmp)
303 goto err;
304
305 *tmp = (long long) offchip[i].plen;
306 }
307
308 free(offchip);
309 return (PyObject *) py_offchip;
310
311err:
312 PyArray_free(py_offchip);
313err_alloc:
314 PyErr_Format(PyExc_ValueError, "pm_get_preemption Error");
315 cleanup();
316 return NULL;
317}
318
319static PyMethodDef PmMethods[] = {
320 {"load", pm_load, METH_VARARGS, "Load data from raw files"},
321 {"getPreemption", pm_get_preemption, METH_VARARGS,
322 "Get preemption overheads - length"},
323 {"getL2Migration", pm_get_samel2, METH_VARARGS,
324 "Get L2 Migration overheads - length"},
325 {"getOnChipMigration", pm_get_samechip, METH_VARARGS,
326 "Get Chip (L2 or L3) overheads - length"},
327 {"getOffChipMigration", pm_get_offchip, METH_VARARGS,
328 "Get Off Chip overheads - length"},
329 {NULL, NULL, 0, NULL}
330};
331
332PyMODINIT_FUNC initpm(void)
333{
334 PyObject *pm;
335 pm = Py_InitModule("pm", PmMethods);
336 if(!pm)
337 return;
338
339 /* required by NumPy */
340 import_array();
341}
342