Numba不接受dtype为object的NumPy数组。

5

我有一个空数组,想要在每个索引[i,j]处填充任意长度的列表。因此,我初始化了一个空数组,它应该保存像这样的对象:

@jit(nopython=True, parrallel=True)
def numba_function():
    values          = np.empty((length, length), dtype=object)
    for i in range(10):
        for j in range(10):
            a_list_of_things = [1,2,3,4]
            values[i,j] = a_list_of_things

这个出错了:

 TypingError: Failed in nopython mode pipeline (step: nopython frontend) Untyped global name 'object': cannot determine Numba type of <class 'type'>

如果我通过设置nopython=False关闭numba,则代码可以正常工作。在values数组中设置dtype=list并不能改善情况。有没有什么聪明的技巧可以克服这个问题?

嗨@TrebledJ,是的,我的帖子中有一个错别字。我现在已经在我的mwe中添加了@!(如果没有它,就会出现未定义变量njit...) - Sebastiano1991
(我实际上在我的代码中使用的是@jit而不是@njit,已更新!) - Sebastiano1991
1个回答

4

Numba在nopython模式下(从版本0.43.1开始)不支持对象数组。

正确的方式是输入一个对象数组:

import numba as nb
import numpy as np

@nb.njit
def numba_function():
    values = np.empty((2, 2), np.object_)
    return values

但是如上所述,那样是不起作用的:
TypingError: Failed in nopython mode pipeline (step: nopython frontend)
Internal error at resolving type of attribute "object_" of "$0.4":
NotImplementedError: object

这也在numba文档中提到:

2.7.1. 标量类型

Numba支持以下Numpy标量类型:

  • 整数:所有带符号或无符号的整数,以及任何宽度长达64位
  • 布尔值
  • 实数:单精度(32位)和双精度(64位)实数
  • 复数:单精度(2x32位)和双精度(2x64位)复数
  • 日期时间和时间戳:任何单位的日期时间和时间戳
  • 字符序列(但不能对它们执行任何操作)
  • 结构化标量:由以上任意类型和数组组成的结构化标量

不支持以下标量类型和特性:

  • 任意Python对象
  • 半精度和扩展精度实数和复数
  • 嵌套的结构化标量,结构化标量的字段中不能包含其他结构化标量

[...]

2.7.2. 数组类型

支持任何以上标量类型的Numpy数组,无论其形状或布局如何。

(强调我的)
由于 dtype=object 允许任意Python对象,因此不受支持。而 dtype=list 等效于 dtype=object (documentation)

Built-in Python types

Several python types are equivalent to a corresponding array scalar when used to generate a dtype object:

int           np.int_
bool          np.bool_
float         np.float_
complex       np.cfloat
bytes         np.bytes_
str           np.bytes_ (Python2) or np.unicode_ (Python3)
unicode       np.unicode_
buffer        np.void
(all others)  np.object_

所有这些都说了:使用 object 数组会非常缓慢,这适用于 NumPy 数组和 numba 函数。每当您选择使用这种 object 数组时,您隐含地决定不要高性能。

因此,如果您想要性能并使用 NumPy 数组,则需要首先重写它,以便不使用对象数组,如果仍然太慢,则可以考虑将 numba 应用于非对象数组。


谢谢您的解释。您能指出一个起点,让我了解如何高效地实现“在给定索引处存储任意长度结果”类型的问题吗? - Sebastiano1991
1
根据我的经验,NumPy不适合“不规则数据结构”。解决方案很大程度上取决于您要解决的问题类型,没有完美的通用解决方案。在大多数情况下,Python列表已经足够快(可以是不规则的)。但是,正如所述,这取决于您遇到的问题,如果涉及“重量级数值计算”和其他因素,即设置瓶颈或操作,什么操作,它是否真的是任意长度还是有约束条件。 - MSeifert
然而,这超出了应在评论中讨论的内容范围和应该讨论的内容。如果您正在寻求有关实际问题的帮助,则应该提出新问题,包括要求和最优化的工作方法,您认为当前方法效率过低。 - MSeifert

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接