我有以下 MWE:
import numba as nb
@nb.njit(nb.uint64(nb.uint64))
def popcount(x):
b=0
while(x > 0):
x &= x - 1
b+=1
return b
print(popcount(43))
它失败了:
numba.core.errors.TypingError: Failed in nopython mode pipeline (step: nopython frontend)
No implementation of function Function(<built-in function iand>) found for signature:
>>> iand(float64, float64)
There are 8 candidate implementations:
- Of which 4 did not match due to:
Overload of function 'iand': File: <numerous>: Line N/A.
With argument(s): '(float64, float64)':
No match.
- Of which 2 did not match due to:
Operator Overload in function 'iand': File: unknown: Line unknown.
With argument(s): '(float64, float64)':
No match for registered cases:
* (bool, bool) -> bool
* (int64, int64) -> int64
* (int64, uint64) -> int64
* (uint64, int64) -> int64
* (uint64, uint64) -> uint64
- Of which 2 did not match due to:
Overload in function 'gen_operator_impl.<locals>._ol_set_operator': File: numba/cpython/setobj.py: Line 1508.
With argument(s): '(float64, float64)':
Rejected as the implementation raised a specific error:
TypingError: All arguments must be Sets, got (float64, float64)
raised from /home/user/python/mypython3.10/lib/python3.10/site-packages/numba/cpython/setobj.py:108
During: typing of intrinsic-call at /home/user/python/popcount.py (7)
File "popcount.py", line 7:
def popcount(x):
<source elided>
while(x > 0):
x &= x - 1
^
为此使用 uint64 有什么问题吗?
即使我使用,代码也会失败并显示相同的消息:
print(popcount(nb.uint64(43))
这就是 NumPy uint64 的尴尬之处。根据 NumPy dtype 规则,标准 Python
int
被处理为带符号的 numpy.int_
dtype。没有足够大的整数数据类型可以容纳 uint64 数据类型和有符号数据类型的所有值,因此在混合 uint64/int 运算中,NumPy 将两个操作数都转换为 float64!
您不能将
&
与浮点数据类型一起使用,并且 Numba 遵循此处的 NumPy 规则,因此会出现错误。
要编译代码,您可以显式转换为
np.uint64()
类型:
import numba as nb
@nb.njit(nb.uint64(nb.uint64))
def popcount(x):
b = 0
while x > 0:
x &= nb.uint64(x - 1)
b += 1
return b
print(popcount(43))
打印:
4