Skip to content
This repository was archived by the owner on Feb 2, 2024. It is now read-only.

Commit 980e347

Browse files
author
Ehsan Totoni
committed
copy meminfo allocs from Numba to be cache safe (TODO numba C API)
1 parent d79a316 commit 980e347

4 files changed

Lines changed: 156 additions & 63 deletions

File tree

hpat/_meminfo.h

Lines changed: 155 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,160 @@
11
#ifndef _MEMINFO_INCLUDED
22
#define _MEMINFO_INCLUDED
33

4-
#include "_import_py.h"
5-
#include <numba/runtime/nrt.h>
6-
7-
/* Import MemInfo_* from numba.runtime._nrt_python.
8-
*/
9-
static void *
10-
import_meminfo_func(const char * func) {
11-
#define CHECK(expr, msg) if(!(expr)){std::cerr << msg << std::endl; PyGILState_Release(gilstate); return NULL;}
12-
auto gilstate = PyGILState_Ensure();
13-
PyObject * helperdct = import_sym("numba.runtime._nrt_python", "c_helpers");
14-
CHECK(helperdct, "getting numba.runtime._nrt_python.c_helpers failed");
15-
/* helperdct[func] */
16-
PyObject * mi_rel_fn = PyDict_GetItemString(helperdct, func);
17-
CHECK(mi_rel_fn, "getting meminfo func failed");
18-
void * fnptr = PyLong_AsVoidPtr(mi_rel_fn);
19-
20-
Py_XDECREF(helperdct);
21-
PyGILState_Release(gilstate);
22-
return fnptr;
23-
#undef CHECK
24-
}
25-
26-
typedef void (*MemInfo_release_type)(void*);
27-
typedef MemInfo* (*MemInfo_alloc_aligned_type)(size_t size, unsigned align);
28-
typedef void* (*MemInfo_data_type)(MemInfo* mi);
4+
// #include "_import_py.h"
5+
// #include <numba/runtime/nrt.h>
296

7+
// /* Import MemInfo_* from numba.runtime._nrt_python.
8+
// */
9+
// static void *
10+
// import_meminfo_func(const char * func) {
11+
// #define CHECK(expr, msg) if(!(expr)){std::cerr << msg << std::endl; PyGILState_Release(gilstate); return NULL;}
12+
// auto gilstate = PyGILState_Ensure();
13+
// PyObject * helperdct = import_sym("numba.runtime._nrt_python", "c_helpers");
14+
// CHECK(helperdct, "getting numba.runtime._nrt_python.c_helpers failed");
15+
// /* helperdct[func] */
16+
// PyObject * mi_rel_fn = PyDict_GetItemString(helperdct, func);
17+
// CHECK(mi_rel_fn, "getting meminfo func failed");
18+
// void * fnptr = PyLong_AsVoidPtr(mi_rel_fn);
19+
20+
// Py_XDECREF(helperdct);
21+
// PyGILState_Release(gilstate);
22+
// return fnptr;
23+
// #undef CHECK
24+
// }
25+
26+
// typedef void (*MemInfo_release_type)(void*);
27+
// typedef MemInfo* (*MemInfo_alloc_aligned_type)(size_t size, unsigned align);
28+
// typedef void* (*MemInfo_data_type)(MemInfo* mi);
29+
30+
31+
32+
// ******** copied from Numba
33+
// TODO: make Numba C library
34+
typedef void (*NRT_dtor_function)(void *ptr, size_t size, void *info);
35+
struct MemInfo {
36+
size_t refct;
37+
NRT_dtor_function dtor;
38+
void *dtor_info;
39+
void *data;
40+
size_t size; /* only used for NRT allocated memory */
41+
};
42+
43+
typedef struct MemInfo NRT_MemInfo;
44+
45+
46+
void nrt_debug_print(char *fmt, ...) {
47+
va_list args;
48+
49+
va_start(args, fmt);
50+
vfprintf(stderr, fmt, args);
51+
va_end(args);
52+
}
53+
54+
55+
#if 0
56+
# define NRT_Debug(X) X
57+
#else
58+
# define NRT_Debug(X) if (0) { X; }
3059
#endif
60+
61+
#if !defined MIN
62+
#define MIN(a, b) ((a) < (b)) ? (a) : (b)
63+
#endif
64+
65+
void NRT_Free(void *ptr) {
66+
NRT_Debug(nrt_debug_print("NRT_Free %p\n", ptr));
67+
free(ptr);
68+
// TheMSys.allocator.free(ptr);
69+
// TheMSys.atomic_inc(&TheMSys.stats_free);
70+
}
71+
72+
73+
void NRT_MemInfo_destroy(NRT_MemInfo *mi) {
74+
NRT_Free(mi);
75+
// TheMSys.atomic_inc(&TheMSys.stats_mi_free);
76+
}
77+
78+
79+
void NRT_MemInfo_call_dtor(NRT_MemInfo *mi) {
80+
NRT_Debug(nrt_debug_print("NRT_MemInfo_call_dtor %p\n", mi));
81+
if (mi->dtor)// && !TheMSys.shutting)
82+
/* We have a destructor and the system is not shutting down */
83+
mi->dtor(mi->data, mi->size, mi->dtor_info);
84+
/* Clear and release MemInfo */
85+
NRT_MemInfo_destroy(mi);
86+
}
87+
88+
89+
90+
void* NRT_Allocate(size_t size) {
91+
// void *ptr = TheMSys.allocator.malloc(size);
92+
void *ptr = malloc(size);
93+
NRT_Debug(nrt_debug_print("NRT_Allocate bytes=%zu ptr=%p\n", size, ptr));
94+
// TheMSys.atomic_inc(&TheMSys.stats_alloc);
95+
return ptr;
96+
}
97+
98+
99+
static
100+
void *nrt_allocate_meminfo_and_data(size_t size, NRT_MemInfo **mi_out) {
101+
NRT_MemInfo *mi;
102+
char *base = (char*) NRT_Allocate(sizeof(NRT_MemInfo) + size);
103+
mi = (NRT_MemInfo *) base;
104+
*mi_out = mi;
105+
return base + sizeof(NRT_MemInfo);
106+
}
107+
108+
void NRT_MemInfo_init(NRT_MemInfo *mi,void *data, size_t size,
109+
NRT_dtor_function dtor, void *dtor_info)
110+
{
111+
mi->refct = 1; /* starts with 1 refct */
112+
mi->dtor = dtor;
113+
mi->dtor_info = dtor_info;
114+
mi->data = data;
115+
mi->size = size;
116+
/* Update stats */
117+
// TheMSys.atomic_inc(&TheMSys.stats_mi_alloc);
118+
}
119+
120+
121+
static
122+
void nrt_internal_dtor_safe(void *ptr, size_t size, void *info) {
123+
NRT_Debug(nrt_debug_print("nrt_internal_dtor_safe %p, %p\n", ptr, info));
124+
/* See NRT_MemInfo_alloc_safe() */
125+
memset(ptr, 0xDE, MIN(size, 256));
126+
}
127+
128+
129+
static
130+
void nrt_internal_custom_dtor_safe(void *ptr, size_t size, void *info) {
131+
NRT_dtor_function dtor = (NRT_dtor_function) info;
132+
NRT_Debug(nrt_debug_print("nrt_internal_custom_dtor_safe %p, %p\n",
133+
ptr, info));
134+
if (dtor) {
135+
dtor(ptr, size, NULL);
136+
}
137+
138+
nrt_internal_dtor_safe(ptr, size, NULL);
139+
}
140+
141+
142+
NRT_MemInfo* NRT_MemInfo_alloc_dtor_safe(size_t size, NRT_dtor_function dtor) {
143+
NRT_MemInfo *mi;
144+
void *data = nrt_allocate_meminfo_and_data(size, &mi);
145+
/* Only fill up a couple cachelines with debug markers, to minimize
146+
overhead. */
147+
memset(data, 0xCB, MIN(size, 256));
148+
NRT_Debug(nrt_debug_print("NRT_MemInfo_alloc_dtor_safe %p %zu\n", data, size));
149+
NRT_MemInfo_init(mi, data, size, nrt_internal_custom_dtor_safe, (void*) dtor);
150+
return mi;
151+
}
152+
153+
154+
NRT_MemInfo *NRT_MemInfo_alloc_safe(size_t size) {
155+
return NRT_MemInfo_alloc_dtor_safe(size, NULL);
156+
}
157+
158+
159+
160+
#endif // #ifndef _MEMINFO_INCLUDED

hpat/_str_decode.cpp

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,6 @@
11
#include <Python.h>
22
#include <iostream>
3-
4-
// ******** copied from Numba
5-
// TODO: make Numba C library
6-
typedef void (*NRT_dtor_function)(void *ptr, size_t size, void *info);
7-
struct MemInfo {
8-
size_t refct;
9-
NRT_dtor_function dtor;
10-
void *dtor_info;
11-
void *data;
12-
size_t size; /* only used for NRT allocated memory */
13-
};
14-
15-
typedef struct MemInfo NRT_MemInfo;
16-
17-
18-
NRT_MemInfo* (*NRT_MemInfo_alloc_safe)(size_t);
19-
void (*NRT_MemInfo_call_dtor)(NRT_MemInfo*);
20-
21-
// initialize allocator/deallocator from Numba pointers. need to be set before calling decode
22-
void init_memsys(NRT_MemInfo* (*_NRT_MemInfo_alloc_safe)(size_t), void (*_NRT_MemInfo_call_dtor)(NRT_MemInfo*))
23-
{
24-
NRT_MemInfo_alloc_safe = _NRT_MemInfo_alloc_safe;
25-
NRT_MemInfo_call_dtor = _NRT_MemInfo_call_dtor;
26-
}
3+
#include "_meminfo.h"
274

285

296
// ******** ported from CPython 31e8d69bfe7cf5d4ffe0967cb225d2a8a229cc97

hpat/_str_ext.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,8 +213,6 @@ PyMODINIT_FUNC PyInit_hstr_ext(void) {
213213
PyLong_FromVoidPtr((void*)(&array_getptr1)));
214214
PyObject_SetAttrString(m, "array_setitem",
215215
PyLong_FromVoidPtr((void*)(&array_setitem)));
216-
PyObject_SetAttrString(m, "init_memsys",
217-
PyLong_FromVoidPtr((void*)(&init_memsys)));
218216
PyObject_SetAttrString(m, "decode_utf8",
219217
PyLong_FromVoidPtr((void*)(&decode_utf8)));
220218
PyObject_SetAttrString(m, "get_utf8_size",

hpat/str_arr_ext.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -598,7 +598,6 @@ def str_arr_len(str_arr):
598598
ll.add_symbol('str_arr_to_float64', hstr_ext.str_arr_to_float64)
599599
ll.add_symbol('dtor_string_array', hstr_ext.dtor_string_array)
600600
ll.add_symbol('c_glob', hstr_ext.c_glob)
601-
ll.add_symbol('init_memsys', hstr_ext.init_memsys)
602601
ll.add_symbol('decode_utf8', hstr_ext.decode_utf8)
603602
ll.add_symbol('get_utf8_size', hstr_ext.get_utf8_size)
604603

@@ -1028,17 +1027,6 @@ def decode_utf8(typingctx, ptr_t, len_t=None):
10281027
def codegen(context, builder, sig, args):
10291028
ptr, length = args
10301029

1031-
# initialize alloc/dealloc from Numba's runtime pointers
1032-
allocator = context.get_constant(types.intp,
1033-
numba.runtime._nrt_python.c_helpers['MemInfo_alloc_safe'])
1034-
deallocator = context.get_constant(types.intp,
1035-
numba.runtime._nrt_python.c_helpers['MemInfo_call_dtor'])
1036-
fnty = lir.FunctionType(lir.VoidType(), [lir.IntType(64),
1037-
lir.IntType(64)])
1038-
fn_init_memsys = builder.module.get_or_insert_function(
1039-
fnty, name="init_memsys")
1040-
builder.call(fn_init_memsys, [allocator, deallocator])
1041-
10421030
# create str and call decode with internal pointers
10431031
uni_str = cgutils.create_struct_proxy(string_type)(context, builder)
10441032
fnty = lir.FunctionType(lir.VoidType(), [lir.IntType(8).as_pointer(),

0 commit comments

Comments
 (0)