有关类型化内存视图的Cython文档列出了三种分配给类型化内存视图的方法:
np.ndarray和cython.view.array.假设我没有从外部传入我的cython函数的数据,而是想分配内存并将其作为a返回np.ndarray,我选择了哪些选项?还假设该缓冲区的大小不是编译时常量,即我不能在堆栈上分配,但需要malloc选项1.
因此,3个选项可以解释如下:
from libc.stdlib cimport malloc, free
cimport numpy as np
from cython cimport view
np.import_array()
def memview_malloc(int N):
cdef int * m = <int *>malloc(N * sizeof(int))
cdef int[::1] b = <int[:N]>m
free(<void *>m)
def memview_ndarray(int N):
cdef int[::1] b = np.empty(N, dtype=np.int32)
def memview_cyarray(int N):
cdef int[::1] b = view.array(shape=(N,), itemsize=sizeof(int), format="i")
Run Code Online (Sandbox Code Playgroud)
让我感到惊讶的是,在所有三种情况下,Cython为内存分配生成了大量代码,特别是调用__Pyx_PyObject_to_MemoryviewSlice_dc_int.这表明(我可能在这里错了,我对Cython内部工作的洞察力非常有限),它首先创建一个Python对象,然后将其"转换"到内存视图中,这似乎是不必要的开销.
一个简单的基准测试并未揭示三种方法之间存在很大差异,其中2是最薄弱的方法.
推荐三种方法中的哪一种?或者有更好的选择吗? …
在这个答案的指导下,我开始建立管道,用于根据数据帧的 dtype 处理数据帧列。但是在得到一些意外的输出和一些调试之后,我最终得到了测试数据帧和测试数据类型检查:
# Creating test dataframe
test = pd.DataFrame({'bool' :[False, True], 'int':[-1,2],'float': [-2.5, 3.4],
'compl':np.array([1-1j, 5]),
'dt' :[pd.Timestamp('2013-01-02'), pd.Timestamp('2016-10-20')],
'td' :[pd.Timestamp('2012-03-02')- pd.Timestamp('2016-10-20'),
pd.Timestamp('2010-07-12')- pd.Timestamp('2000-11-10')],
'prd' :[pd.Period('2002-03','D'), pd.Period('2012-02-01', 'D')],
'intrv':pd.arrays.IntervalArray([pd.Interval(0, 0.1), pd.Interval(1, 5)]),
'str' :['s1', 's2'],
'cat' :[1, -1],
'obj' :[[1,2,3], [5435,35,-52,14]]
})
test['cat'] = test['cat'].astype('category')
test
test.dtypes
# Testing types
types = list(test.columns)
df_types = pd.DataFrame(np.zeros((len(types),len(types)), dtype=bool),
index = ['is_'+el for el in types],
columns = types)
for col in test.columns:
df_types.at['is_bool', col] = pd.api.types.is_bool_dtype(test[col])
df_types.at['is_int' , …Run Code Online (Sandbox Code Playgroud) pd.MultiIndex使用不同的类方法创建相等的性能测试:
import pandas as pd
size_mult = 8
d1 = [1]*10**size_mult
d2 = [2]*10**size_mult
pd.__version__
Run Code Online (Sandbox Code Playgroud)
'0.24.2'
Run Code Online (Sandbox Code Playgroud)
即.from_arrays,from_tuples,from_frame:
# Cell from_arrays
%%time
index_arr = pd.MultiIndex.from_arrays([d1, d2], names=['a', 'b'])
# Cell from_tuples
%%time
index_tup = pd.MultiIndex.from_tuples(zip(d1, d2), names=['a', 'b'])
# Cell from_frame
%%time
df = pd.DataFrame({'a':d1, 'b':d2})
index_frm = pd.MultiIndex.from_frame(df)
Run Code Online (Sandbox Code Playgroud)
单元的相应输出:
# from_arrays
CPU times: user 1min 15s, sys: 6.58 s, total: 1min 21s
Wall time: 1min 21s
# from_tuples
CPU times: user 26.4 s, …Run Code Online (Sandbox Code Playgroud) 在 pytest 中参数化测试和夹具时,pytest 似乎急切地评估所有参数并在开始执行测试之前构建一些测试列表数据结构。
这是在 2 种情况下的问题:
因此我的问题是:是否有可能告诉 pytest 即时评估参数(即懒惰)?
对于int对象,可以这样使用cpython的cimported函数:
%%cython
from decimal import Decimal
from cpython cimport PyLong_Check
val_decimal = Decimal(1)
print(PyLong_Check(val_decimal))
Run Code Online (Sandbox Code Playgroud)
False
Run Code Online (Sandbox Code Playgroud)
但似乎没有对应的功能decimal。
另一种方法是这样使用try-except:
%%cython
from decimal import Decimal
from cpython cimport PyFloat_Check
cdef bint check(object val):
if PyFloat_Check(val):
return False
try:
float(val)
return True
except:
return False
val_decimal = Decimal(1.1)
val_float = 1.1
print (check(val_decimal))
print (check(val_float))
Run Code Online (Sandbox Code Playgroud)
True
False
Run Code Online (Sandbox Code Playgroud)
但这不仅会捕获decimal所有可能转换为的内容float。例如,也check("1.1")返回True(可能也排除了'str',check()但这看起来仅是'替代方法'-无法保证check()现在仅在上触发decimal)。
那么检查decimalcython 的正确方法是什么?
python ×5
cython ×2
pandas ×2
performance ×2
buffer ×1
dataframe ×1
memory ×1
multi-index ×1
pytest ×1
python-3.x ×1
types ×1