Cython:优化原生Python内存视图

4
我有一个来自外部Python库的函数,它返回一个memoryview对象,我想在Cython中处理它。
有没有一种方法可以将其转换为字节的类型化内存视图(无需复制)以提高效率?我该怎么做呢?这种方法行不通:
mv = memoryview(b'1234')
cdef char[:] *tmv
tmv = mv
     ^
------------------------------------------------------------

/home/me/.cache/ipython/cython/_cython_magic_f9f608355444e2d6828580906623cea8.pyx:3:6: Cannot convert Python object to '__Pyx_memviewslice *'

1
如果你还没有看过的话,你可能想要看一下这个stackoverflow问题 - CodeSurgeon
另外,既然Python的memoryviews是从bytearray创建的,为什么不直接将bytearray传递给Cython呢? - CodeSurgeon
@CodeSurgeon 我对表达式mv = memoryview(b'1234')感到困惑,即mv实际上是第三方库函数的结果。 - user3758232
1个回答

3

这个答案 是@CodeSurgeon提供的一种可能的方法。然而,从Cython 0.28开始,我们有了一种更加简洁的方式——只读的内存视图:

%%cython
mv = memoryview(b'1234')
cdef const unsigned char[:] tmv=mv  #"const" is possible since Cython 0.28

显然,您只能从这个memoryview中读取(这是一件好事),并且没有涉及到复制。你还可以说:但这是unsigned char而不是char!没错,这也是一件好事:bytes是unsigned chars,类型化memoryviews的整个重点在于您不会混淆类型!我认为链接的解决方案有点危险的另一个原因是,您可以使用C的全部功能来自毁长城,因为它会强制转换类型和常量性。例如,请参见:
%%cython    
def bad_things(a):
   cdef const unsigned char[:] safe=a
   cdef char *unsafe=<char *> &safe[0] #who needs const and types anyway?
   unsafe[0]=52   #replace through `4`

现在:

 >>> A=b'a'
 >>> bad_things(A)
 >>> print(A)   #take it Python - I pwned your immutability!
 b'4'
 >>> print(b'a')
 b'4'
 >>> #Help! What are you doing Python?

因为Python有一组小字符串池,它们是不可变的(至少Python认为是这样的),而我们已经将与b'a'相关联的对象更改为b'4',因此我们应该做好迎接有趣结果和开心调试的准备...
总的来说,这很简单:坚持使用类型内存视图以保证类型和常量安全。

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