Python 和 Numba:尽可能快地访问结构化 numpy 数组元素

jjj*_*ayn 5 python arrays numpy numba

我有一个具有以下数据类型的大型结构化 numpy 数组:

\n\n
> my_array.dtype\n= dtype([('field1', '<i4', (32,)), ('field2', '<i4', (425,)), \n         ('field3', '<i4', (8021,))])\n
Run Code Online (Sandbox Code Playgroud)\n\n

我的目标是尽快访问任何给定的单个元素。如果我按字段名称对数组进行切片,Numba 就能够在非 python 模式下执行。

\n\n
@numba.njit\ndef test_function(my_array_sliced):\n    for i in range(len(my_array_sliced)):\n        _ = my_array_sliced[i]\n    return\n\n> %timeit test_function(my_array['field1'])\n  399 ns \xc2\xb1 10.8 ns per loop (mean \xc2\xb1 std. dev. of 7 runs, 1000000 loops each)\n
Run Code Online (Sandbox Code Playgroud)\n\n

这效果很好,但我意识到,通过使用“常量”字段名称稍微不同地访问我的数组,我能够在性能方面获得更好的结果:

\n\n
@numba.njit\ndef test_function2(my_array):\n    for i in range(len(my_array)):\n        _ = my_array[i]['field1']\n    return\n\n> %timeit test_function2(my_array)\n  280 ns \xc2\xb1 5.88 ns per loop (mean \xc2\xb1 std. dev. of 7 runs, 10000000 loops each)\n
Run Code Online (Sandbox Code Playgroud)\n\n

399ns 与 280ns - 这是一个很大的区别!我真的无法说出为什么会有这样的差异。

\n\n

如果我尝试通过向函数添加参数来获得更好的性能,我会收到输入错误。

\n\n
@numba.njit\ndef test_function3(my_array, v):\n    for i in range(len(my_array)):\n        _ = my_array[i][v]\n    return\n\n\n> %timeit test_function3(my_array, 0):\n  TypingError: Failed at nopython (nopython frontend)\n  Invalid usage of getitem with parameters (Record([('field1', '<i4', \n  (32,)), ('field2', '<i4', (425,)), ('field3', '<i4', (8021,))]), int64)\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果我用“field1”等字符串参数替换 int 参数,也会发生类似的情况(尽管如此,我一开始就不应该使用字符串,因为 Numba 并不真正处理它们)。

\n\n

因此,就性能而言,目前最好的选择是为每个字段名称创建不同的函数。这显然是疯了。我应该如何修改我的代码以实现最佳性能?

\n\n

谢谢你!

\n