Mag*_*n88 8 python numpy cython
如果它应该能够同时处理float和double,那么在cython中声明numpy数组的最佳方法是什么?
我想用内存视图是不可能的,因为数据类型是至关重要的,但是对于ndarray有什么方法可以给它一个通用浮点类型,这仍然有利于cython的快速性?
所以这就是我通常会做的事情:
def F( np.ndarray A):
A += 10
Run Code Online (Sandbox Code Playgroud)
我已经看到还有:
def F( np.ndarray[np.float32_t, ndim=2] A):
A += 10
Run Code Online (Sandbox Code Playgroud)
但这又会给这个类型增加一点尺寸.我还想过根据位大小(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
Run Code Online (Sandbox Code Playgroud)
当我现在用两个np.float32数组调用该函数时,我得到了错误
ValueError:Buffer dtype不匹配,预期'float'但得到'double'
如果我不在制动器中使用类型定义,Rot那么它会读取np.ndarray[floating, ndim=3] Rot = np.empty((T,3,3))然后我得到ndarray,它工作正常.你碰巧有一个指针,告诉我我做错了什么吗?
Vee*_*rac 12
Well this is actually really easy with fused types support:
This goes inside your code.
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
Run Code Online (Sandbox Code Playgroud)
Of course, there are loads of ways of doing this:
Name this fuzed.pyx. There's no need to compile or run
cythonon it; it's handled bypyximport. Don't usepyximportfor production code, though, as you should typically only ship.cfiles.
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):
# ...
Run Code Online (Sandbox Code Playgroud)
and here's a little test script:
Name this test.py and run it as a normal Python script:
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))
Run Code Online (Sandbox Code Playgroud)
It's worth noting that fused types are specialised at compilation, and are constant for a particular function invocation. The empty Numpy array you make is always of a double type, but you assign it to either a 32-bit float or a 64-bit float. Here's what you should do:
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
Run Code Online (Sandbox Code Playgroud)
and some tests to prove the point:
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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4165 次 |
| 最近记录: |