如果它能够同时处理float和double,那么在cython中声明numpy数组的最佳方法是什么?
我想因为数据类型是至关重要的,但是对于内存视图来说它是不可能的,但是对于一个ndarray,有没有办法给它一个通用浮点类型,这仍然可以从cython的快速性中受益? / p>
所以这就是我通常会做的事情:
def F( np.ndarray A):
A += 10
我已经看到还有:
def F( np.ndarray[np.float32_t, ndim=2] A):
A += 10
但是这又会为该类型提供一点尺寸。我还想到了根据位大小(32或64)在函数内部创建内存视图的行。
任何想法都受到高度赞赏
非常感谢floating
类型的提示。我试过这样的
import numpy as np
cimport numpy as np
import cython
cimport cython
from libc.math cimport sqrt, abs
from cython cimport floating
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.nonecheck(False)
def Rot_Matrix(np.ndarray[floating, ndim=3] Fit_X,
np.ndarray[floating, ndim=3] Ref_X,
weight = None):
cdef:
unsigned int t, T = Fit_X.shape[0]
unsigned int n, N = Fit_X.shape[1]
np.ndarray[floating, ndim=3] Rot = np.empty((T,3,3))
return Rot
当我现在用两个np.float32数组调用该函数时,我得到了错误
ValueError:缓冲区dtype不匹配,预期'浮动'但得到了双倍的'
如果我没有在Rot
的制动器中使用类型定义,那么它会读取np.ndarray[floating, ndim=3] Rot = np.empty((T,3,3))
然后我得到ndarray,它运行正常。你碰巧有一个指针告诉我我做错了吗?
答案 0 :(得分:12)
对于融合类型支持,这实际上非常简单:
这会进入你的代码。
from cython cimport floating
def cythonfloating_memoryview(floating[:, :] array):
cdef int i, j
for i in range(array.shape[0]):
for j in range(array.shape[1]):
array[i, j] += 10
当然,有很多方法可以做到这一点:
将此 fuzed.pyx 命名为。没有必要在其上编译或运行
cython
;它由pyximport
处理。但是,不要将pyximport
用于生产代码,因为您通常只应提供.c
个文件。
from cython cimport floating
from numpy import float32_t, float64_t, ndarray
ctypedef fused myfloating:
float32_t
float64_t
def cythonfloating_memoryview(floating[:, :] array):
# ...
def cythonfloating_buffer(ndarray[floating, ndim=2] array):
# ...
def myfloating_memoryview(myfloating[:, :] array):
# ...
def myfloating_buffer(ndarray[myfloating, ndim=2] array):
# ...
这是一个小测试脚本:
将此 test.py 命名为普通Python脚本:
import pyximport
pyximport.install()
import fuzed
import numpy
functions = [
fuzed.cythonfloating_memoryview,
fuzed.cythonfloating_buffer,
fuzed.myfloating_memoryview,
fuzed.myfloating_buffer,
]
for function in functions:
floats_32 = numpy.zeros((100, 100), "float32")
doubles_32 = numpy.zeros((100, 100), "float64")
function(floats_32)
function(doubles_32)
print(repr(floats_32))
print(repr(doubles_32))
值得注意的是,融合类型专门用于编译,并且对于特定的函数调用是常量。您创建的空Numpy数组始终为double
类型,但您可以将其分配给32位浮点数或64位浮点数。这是你应该做的:
from cython cimport floating
import numpy
def do_some_things(floating[:] input):
cdef floating[:] output
if floating is float:
output = numpy.empty(10, dtype="float32")
elif floating is double:
output = numpy.empty(10, dtype="float64")
else:
raise ValueError("Unknown floating type.")
return output
和一些测试来证明这一点:
import pyximport
pyximport.install()
#>>> (None, None)
import floatingtest
import numpy
floatingtest.do_some_things(numpy.empty(10, dtype="float32"))
#>>> <MemoryView of 'ndarray' at 0x7f0a514b3d88>
floatingtest.do_some_things(numpy.empty(10, dtype="float32")).itemsize
#>>> 4
floatingtest.do_some_things(numpy.empty(10, dtype="float64"))
#>>> <MemoryView of 'ndarray' at 0x7f0a514b3d88>
floatingtest.do_some_things(numpy.empty(10, dtype="float64")).itemsize
#>>> 8
答案 1 :(得分:2)
融合类型只能在函数声明中使用。我能想出的最好的比喻是C ++中的模板。
创建一个可以与float32 / 64一起使用的函数
from cython import floating, numeric
cimport cython
def func_float(floating a):
print cython.typeof(a)
但是,您只能在已经出现在函数声明中的函数中使用Fused Types
。