Python 带字符串数组的Cython prange

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

我试图使用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 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
    声明为
    arx
    ,并展开运行时检查,类似于Cython的
  • 如果应该进行适当的更改,则输入数组中的元素应该足够大,以容纳生成的字符串

所有这些都与
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
    声明为
    arx
    ,并展开运行时检查,类似于Cython的
  • 如果应该进行适当的更改,则输入数组中的元素应该足够大,以容纳生成的字符串

所有这些都与
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,这是不可能的。