我正在尝试找到使用Cython水平汇总一个数组阵列的最快方法。为了开始,我们假设我有一个10 x 100,000随机浮点数的2D数组。我可以创建一个object
数组,每列作为数组中的值,如下所示:
n = 10 ** 5
a = np.random.rand(10, n)
a_obj = np.empty(n, dtype='O')
for i in range(n):
a_obj[i] = a[:, i]
我想做的就是找到每一行的总和。它们都可以通过以下方式进行简单计算:
%timeit a.sum(1)
414 µs ± 24.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit a_obj.sum()
113 ms ± 7.01 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
对象数组慢250倍。
在尝试总结之前,我想及时访问每个元素。在直接遍历每个项目时,Cython无法加快对对象数组的每个成员的访问:
def access_obj(ndarray[object] a):
cdef int i
cdef int nc = len(a)
cdef int nr = len(a[0])
for i in range(nc):
for j in range(nr):
a[i][j]
%timeit access_obj(a_obj)
42.1 ms ± 665 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
但是,我相信我可以使用data
属性访问基础C数组,该属性是memoryview
对象并且访问速度更快:
def access_obj_data(ndarray[object] a):
cdef int i
cdef int nc = len(a)
cdef int nr = len(a[0])
cdef double **data = <double**>a.data
for i in range(nc):
for j in range(nr):
data[i][j]
我认为这个缓存在计时时产生,所以我不得不这样做。
%timeit -n 1 -r 1 access_obj_data(a_obj)
8.17 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
问题在于您无法将a.data
转换为双打C数组。如果我打印出第一列,我会得到以下内容。
5e-324
2.1821467023e-314
2.2428810855e-314
2.1219957915e-314
6.94809615162997e-310
6.94809615163037e-310
2.2772194067e-314
2.182150145e-314
2.1219964234e-314
0.0
有类似的问题,但没有明确的答案是使用有效的代码快速完成此操作的方法。
答案 0 :(得分:0)
我无法评论上面Jan给出的好答案,但请注意
res[i]+=orig[(n_blocks*MAX)*n_cols+j];
在“ //同时计算左行的总和”之后应显示
res[i]+=orig[(n_blocks*MAX+i)*n_cols+j];