假设我想将一个numpy数组传递给一个cdef函数:
cdef double mysum(double[:] arr):
cdef int n = len(arr)
cdef double result = 0
for i in range(n):
result = result + arr[i]
return result
Run Code Online (Sandbox Code Playgroud)
这是处理键入numpy数组的现代方法吗?与这个问题相比:cython/numpy类型的数组
如果我想执行以下操作该怎么办?
cdef double[:] mydifference(int a, int b):
cdef double[:] arr_a = np.arange(a)
cdef double[:] arr_b = np.arange(b)
return arr_a - arr_b
Run Code Online (Sandbox Code Playgroud)
这将返回错误,因为-没有为memoryviews定义.那么,该案件是否应如下处理?
cdef double[:] mydifference(int a, int b):
arr_a = np.arange(a)
arr_b = np.arange(b)
return arr_a - arr_b
Run Code Online (Sandbox Code Playgroud) 在性能方面(代数运算,查找,缓存等),C数组(可以作为C数组公开,或者cython.view.array[Cython数组],或上述两者的内存视图)和NumPy数组(在Cython中应该没有Python开销)
编辑:
我应该提一下,在NumPy数组中使用Cython进行静态类型化,dtypes是NumPy编译时数据类型(例如cdef np.int_t或者cdef np.float32_t),C语言中的类型是C等价物(cdef int_t和cdef float)
EDIT2:
以下是Cython Memoryview文档中的示例,以进一步说明我的问题:
from cython.view cimport array as cvarray
import numpy as np
# Memoryview on a NumPy array
narr = np.arange(27, dtype=np.dtype("i")).reshape((3, 3, 3))
cdef int [:, :, :] narr_view = narr
# Memoryview on a C array
cdef int carr[3][3][3]
cdef int [:, :, :] carr_view = carr
# Memoryview on a Cython …Run Code Online (Sandbox Code Playgroud) 如果我将一个python列表发送到cython函数进行迭代,我想要声明列表项是什么类型的?在cython中循环列表的最佳方法是什么?例如:
#Cython function, passed a list of float items
def cython_f(list example_list):
cdef int i
for i in range(len(example_list)):
#Do stuff
#but list item type not defined?
pass
#Alternative loop
cdef j float #declaration of list item type
for j in example_list:
#Do stuff
pass
Run Code Online (Sandbox Code Playgroud)
尝试定义列表项类型是否获得了任何速度?是否最好传递numpy数组而不是python列表?
由于我发现内存视图方便快捷,我尝试避免在cython中创建NumPy数组并使用给定数组的视图.但是,有时无法避免,不能改变现有阵列而是创建新阵列.在上层函数中,这是不明显的,但在经常被称为子例程的情况下.考虑以下功能
#@cython.profile(False)
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.nonecheck(False)
cdef double [:] vec_eq(double [:] v1, int [:] v2, int cond):
''' Function output corresponds to v1[v2 == cond]'''
cdef unsigned int n = v1.shape[0]
cdef unsigned int n_ = 0
# Size of array to create
cdef size_t i
for i in range(n):
if v2[i] == cond:
n_ += 1
# Create array for selection
cdef double [:] s = np.empty(n_, dtype=np_float) # Slow line
# Copy selection to new array
n_ = 0 …Run Code Online (Sandbox Code Playgroud) 使用Cython,我试图将Python列表转换为Cython数组,反之亦然.Python列表包含0到255范围内的数字,因此我将数组的类型指定为unsigned char数组.这是我的代码来进行转换:
from libc.stdlib cimport malloc
cdef to_array(list pylist):
cdef unsigned char *array
array = <unsigned char *>malloc(len(pylist) * sizeof(unsigned char))
cdef long count = 0
for item in pylist:
array[count] = item
count += 1
return array
cdef to_list(array):
pylist = [item for item in array]
return pylist
def donothing(pylist):
return to_list(to_array(pylist))
Run Code Online (Sandbox Code Playgroud)
问题在于,在Cython数组中生成了多条垃圾数据,并且当转换为Python列表时,垃圾数据会继续存在.例如,donothing应该什么都不做,并将python列表返回给我,不变.这个函数只是用于测试转换,但是当我运行它时,我得到类似的东西:
In[56]: donothing([2,3,4,5])
Out[56]: [2, 3, 4, 5, 128, 28, 184, 6, 161, 148, 185, 69, 106, 101]
Run Code Online (Sandbox Code Playgroud)
这些数据来自代码中的哪里,以及如何清理这些垃圾以免浪费内存?
PS可能有更好的从Python列表中获取数字并将它们注入unsigned char数组的版本.如果是这样,请完全指导我一个更好的方法.
我正在为numpy编写一个新的随机数生成器,当我遇到这个非常奇怪的行为时,根据任意分布生成随机数:
这是test.pyx
#cython: boundscheck=False
#cython: wraparound=False
import numpy as np
cimport numpy as np
cimport cython
def BareBones(np.ndarray[double, ndim=1] a,np.ndarray[double, ndim=1] u,r):
return u
def UntypedWithLoop(a,u,r):
cdef int i,j=0
for i in range(u.shape[0]):
j+=i
return u,j
def BSReplacement(np.ndarray[double, ndim=1] a, np.ndarray[double, ndim=1] u):
cdef np.ndarray[np.int_t, ndim=1] r=np.empty(u.shape[0],dtype=int)
cdef int i,j=0
for i in range(u.shape[0]):
j=i
return r
Run Code Online (Sandbox Code Playgroud)
setup.py
from distutils.core import setup
from Cython.Build import cythonize
setup(name = "simple cython func",ext_modules = cythonize('test.pyx'),)
Run Code Online (Sandbox Code Playgroud)
分析代码
#!/usr/bin/python
from __future__ import division
import …Run Code Online (Sandbox Code Playgroud) 我试图使用Cython内存视图而不创建或使用numpy数组,所以我从来不必编译numpy,但我想返回Python端可以"转换"为numpy数组的东西.例如,我有这个函数,它接受一个2D数组并返回一个新的1d数组:
cimport cython
from cython.view cimport array as cvarray
cpdef int[:] myfunc(int[:,:] input_arr, int arr_len):
cdef int i
# allocate new int array
cdef int[:] new_arr = cvarray(shape=(arr_len,), itemsize=sizeof(int), format="i")
for i in xrange(arr_len):
if input_arr[i, 0] == 1:
new_arr[i] = 0
else:
new_arr[i] = 1
return new_arr
Run Code Online (Sandbox Code Playgroud)
现在从Python我实际上想要将一个numpy数组传递给该函数并将结果视为一个numpy数组:
# From Python
import numpy as np
data = np.array([[0,0,0],[1,0,1]], dtype=np.dtype("i"))
result = myfunc(data, data.shape[0])
# How do I make 'result' accessible as numpy array here??
# ...
result …Run Code Online (Sandbox Code Playgroud) 我有一堆numpy数组作为python对象数组的属性,在cython中,为prange处理做准备(需要nogil),我想创建一个在第一维中"间接"的内存视图,并且其进一步维度引用了numpy数组中的数据.所以,假设objects是一个具有vector属性的对象列表.
我想做的事情如下:
cdef double[ ::cython.view.indirect, ::1 ] vectors
for object in objects:
vectors[ i ] = object.vector
Run Code Online (Sandbox Code Playgroud)
但是,我应该如何初始化"向量"以使其成为可能?如果有可能的话?或者也许内存视图只允许是一个对象的内存视图...在这种情况下还有另一个问题 - 如何动态创建内存视图数组?