Python 带字符串数组的Cython prange
我试图使用prange来处理多个字符串。 由于无法使用python列表执行此操作,因此我使用的是numpy数组 对于浮点数数组,此函数起作用:Python 带字符串数组的Cython prange,python,parallel-processing,cython,Python,Parallel Processing,Cython,我试图使用prange来处理多个字符串。 由于无法使用python列表执行此操作,因此我使用的是numpy数组 对于浮点数数组,此函数起作用: from cython.parallel import prange cimport numpy as np from numpy cimport ndarray as ar cpdef func_float(ar[np.float64_t,cast=True] x, double alpha): cdef int i for i in
from cython.parallel import prange
cimport numpy as np
from numpy cimport ndarray as ar
cpdef func_float(ar[np.float64_t,cast=True] x, double alpha):
cdef int i
for i in prange(x.shape[0], nogil=True):
x[i] = alpha * x[i]
return x
当我尝试这个简单的方法时:
cpdef func_string(ar[np.str,cast=True] x):
cdef int i
for i in prange(x.shape[0], nogil=True):
x[i] = x[i] + str(i)
return x
我明白了
>> func_string(x = np.array(["apple","pear"],dtype=np.str))
File "processing.pyx", line 8, in processing.func_string
cpdef func_string(ar[np.str,cast=True] x):
ValueError: Item size of buffer (20 bytes) does not match size of 'str object' (8 bytes)
我可能遗漏了什么,我找不到替代str的方法。
有没有一种方法可以正确地将prange与字符串数组一起使用?除此之外,代码在cythonized时应该失败,因为您试图在没有gil的情况下创建Python对象(即
str(i)
),您的代码没有做您认为应该做的事情
为了分析正在发生的事情,让我们来看看一个简单的Cython版本:
%%cython -2
cimport numpy as np
from numpy cimport ndarray as ar
cpdef func_string(ar[np.str, cast=True] x):
print(len(x))
从您的错误消息中,可以推断您使用的是Python 3,而Cython扩展是使用构建的(仍然是默认的),因此我在%%Cython
-magic单元格中使用了-2
现在:
>>> x = np.array(["apple", "pear"], dtype=np.str)
>>> func_string(x)
ValueError: Item size of buffer (20 bytes) does not match size of 'str object' (8 bytes)
发生了什么事
x
不是你想象的那样
首先,让我们看看<代码> x>代码>:
>>> x.dtype
<U5
元素没有更改,因为字符串x[0]+str(0)
在写回x
-数组时被截断:只有5个字符的位置!它可以与“pear”
一起工作(在某种程度上,只要生成的字符串不超过5个字符):
>>> x[1] = x[1]+str(1)
>>> x[1]
'pear0'
这一切留给你的是什么
- 您可能希望使用
,而不是字节
(即Unicode
dtype=np.bytes
- 考虑到您不知道编译类型下numpy数组的元素大小,您应该在签名中将输入数组
声明为x
,并展开运行时检查,类似于Cython的arx
- 如果应该进行适当的更改,则输入数组中的元素应该足够大,以容纳生成的字符串
所有这些都与
prange
无关。要使用prange
您不能使用str(i)
,因为它在python对象上运行。除此之外,您的代码在cythonized时应该失败,因为您试图在没有gil的情况下创建python对象(即str(i)
),您的代码没有做您认为应该做的事情
为了分析正在发生的事情,让我们来看看一个简单的Cython版本:
%%cython -2
cimport numpy as np
from numpy cimport ndarray as ar
cpdef func_string(ar[np.str, cast=True] x):
print(len(x))
从您的错误消息中,可以推断您使用的是Python 3,而Cython扩展是使用构建的(仍然是默认的),因此我在%%Cython
-magic单元格中使用了-2
现在:
>>> x = np.array(["apple", "pear"], dtype=np.str)
>>> func_string(x)
ValueError: Item size of buffer (20 bytes) does not match size of 'str object' (8 bytes)
发生了什么事
x
不是你想象的那样
首先,让我们看看<代码> x>代码>:
>>> x.dtype
<U5
元素没有更改,因为字符串x[0]+str(0)
在写回x
-数组时被截断:只有5个字符的位置!它可以与“pear”
一起工作(在某种程度上,只要生成的字符串不超过5个字符):
>>> x[1] = x[1]+str(1)
>>> x[1]
'pear0'
这一切留给你的是什么
- 您可能希望使用
,而不是字节
(即Unicode
dtype=np.bytes
- 考虑到您不知道编译类型下numpy数组的元素大小,您应该在签名中将输入数组
声明为x
,并展开运行时检查,类似于Cython的arx
- 如果应该进行适当的更改,则输入数组中的元素应该足够大,以容纳生成的字符串
所有这些都与
prange
无关。要使用prange
您不能使用str(i)
,因为它在python对象上运行。如果您将prange
更改为range
?@DavidW我想保留prange,这是否有效。更改为范围无效。您使用的是哪种Python/Cython版本?我对你编译的代码感到惊讶,因为str(I)
应该创建一个Python对象,如果没有gil就不可能创建它。如果你将prange
更改为range
,这行得通吗?@DavidW我想保留prange。更改为范围无效。您使用的是哪种Python/Cython版本?我对您编译的代码感到惊讶,因为str(I)
应该创建一个Python对象,如果没有gil,这是不可能的。