Skip to content

Commit d2ca21b

Browse files
committed
MNT: move unpack_bits LUT into global static struct
1 parent 2ffcc71 commit d2ca21b

File tree

3 files changed

+29
-28
lines changed

3 files changed

+29
-28
lines changed

numpy/_core/src/multiarray/compiled_base.c

Lines changed: 3 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1747,15 +1747,6 @@ pack_bits(PyObject *input, int axis, char order)
17471747
static PyObject *
17481748
unpack_bits(PyObject *input, int axis, PyObject *count_obj, char order)
17491749
{
1750-
static int unpack_init = 0;
1751-
/*
1752-
* lookuptable for bitorder big as it has been around longer
1753-
* bitorder little is handled via byteswapping in the loop
1754-
*/
1755-
static union {
1756-
npy_uint8 bytes[8];
1757-
npy_uint64 uint64;
1758-
} unpack_lookup_big[256];
17591750
PyArrayObject *inp;
17601751
PyArrayObject *new = NULL;
17611752
PyArrayObject *out = NULL;
@@ -1841,22 +1832,6 @@ unpack_bits(PyObject *input, int axis, PyObject *count_obj, char order)
18411832
goto fail;
18421833
}
18431834

1844-
/*
1845-
* setup lookup table under GIL, 256 8 byte blocks representing 8 bits
1846-
* expanded to 1/0 bytes
1847-
*/
1848-
if (unpack_init == 0) {
1849-
npy_intp j;
1850-
for (j=0; j < 256; j++) {
1851-
npy_intp k;
1852-
for (k=0; k < 8; k++) {
1853-
npy_uint8 v = (j & (1 << k)) == (1 << k);
1854-
unpack_lookup_big[j].bytes[7 - k] = v;
1855-
}
1856-
}
1857-
unpack_init = 1;
1858-
}
1859-
18601835
count = PyArray_DIM(new, axis) * 8;
18611836
if (outdims[axis] > count) {
18621837
in_n = count / 8;
@@ -1883,15 +1858,15 @@ unpack_bits(PyObject *input, int axis, PyObject *count_obj, char order)
18831858
/* for unity stride we can just copy out of the lookup table */
18841859
if (order == 'b') {
18851860
for (index = 0; index < in_n; index++) {
1886-
npy_uint64 v = unpack_lookup_big[*inptr].uint64;
1861+
npy_uint64 v = npy_ma_global_data->unpack_lookup_big[*inptr].uint64;
18871862
memcpy(outptr, &v, 8);
18881863
outptr += 8;
18891864
inptr += in_stride;
18901865
}
18911866
}
18921867
else {
18931868
for (index = 0; index < in_n; index++) {
1894-
npy_uint64 v = unpack_lookup_big[*inptr].uint64;
1869+
npy_uint64 v = npy_ma_global_data->unpack_lookup_big[*inptr].uint64;
18951870
if (order != 'b') {
18961871
v = npy_bswap8(v);
18971872
}
@@ -1902,7 +1877,7 @@ unpack_bits(PyObject *input, int axis, PyObject *count_obj, char order)
19021877
}
19031878
/* Clean up the tail portion */
19041879
if (in_tail) {
1905-
npy_uint64 v = unpack_lookup_big[*inptr].uint64;
1880+
npy_uint64 v = npy_ma_global_data->unpack_lookup_big[*inptr].uint64;
19061881
if (order != 'b') {
19071882
v = npy_bswap8(v);
19081883
}

numpy/_core/src/multiarray/multiarraymodule.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4990,6 +4990,24 @@ initialize_static_globals(void)
49904990
}
49914991
npy_ma_global_data->optimize = PyLong_AsLong(level);
49924992
Py_DECREF(level);
4993+
4994+
/*
4995+
* see unpack_bits for how this table is used.
4996+
*
4997+
* LUT for bigendian bitorder, littleendian is handled via
4998+
* byteswapping in the loop.
4999+
*
5000+
* 256 8 byte blocks representing 8 bits expanded to 1 or 0 bytes
5001+
*/
5002+
npy_intp j;
5003+
for (j=0; j < 256; j++) {
5004+
npy_intp k;
5005+
for (k=0; k < 8; k++) {
5006+
npy_uint8 v = (j & (1 << k)) == (1 << k);
5007+
npy_ma_global_data->unpack_lookup_big[j].bytes[7 - k] = v;
5008+
}
5009+
}
5010+
49935011
return 0;
49945012
}
49955013

numpy/_core/src/multiarray/multiarraymodule.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,14 @@ typedef struct npy_ma_global_data_struct {
7474
*/
7575
long optimize;
7676

77+
/*
78+
* LUT used by unpack_bits
79+
*/
80+
union {
81+
npy_uint8 bytes[8];
82+
npy_uint64 uint64;
83+
} unpack_lookup_big[256];
84+
7785
/*
7886
* Used for CPU feature detection and dispatch
7987
*

0 commit comments

Comments
 (0)