Cython将numpy ndarray(N,4,2)转换为vector [vector [pair [double,double]]

时间:2017-08-28 11:58:41

标签: python numpy cython

我花了几周的时间将我的cython代码更改为纯C(尽管仍在Cython中)以获得速度并能够移除GIL以进行多线程以获得更高的速度。

在stackoverflow用户的帮助下,我终于成功并获得了一个因子10纯C vs cython与一些python然后通过使用4个线程(prange)在double for循环我的部分代码。

但是为了进入这个循环,我首先必须转换维度(N,4,2)(和(K,4,2))的两个3维numpy ndarraysvector[vector[pair[double,double]]]。 K和N相当大。

为此我正在做:

cdef int N=200000 #Of this order of magnitude
cdef np.ndarray[DTYPE_t,ndim=3] numpy_array=np.random.uniform(size=(N,4,2))
t1=time.time()
cdef vector[vector[pair[double,double]]] c_structure
c_structure.reserve(N)
cdef int i
for i in range(N):
  c_structure.push_back(numpy_array[i])
t2=time.time()

然而,我认为微不足道的这部分代码已经成为我代码的新瓶颈! double for循环使用我的计算机 0.1s (而不是原始实现中的1.11s)单线程,此部分需要 3整秒(每个数组1.5s) !这使我的超级优化代码比原始代码慢了3倍(1.5 * 2 + 0.1)!

我做错了什么?!如何加快这个速度?!

请参阅another related question that I asked

2 个答案:

答案 0 :(得分:2)

您有一个Nx4x2阵列,并且您正在将其转换为vector[vector[pair[double,double]]。在C ++中,向量的向量不是有效的。相反,您应该创建一个4x2结构并创建一个向量。或者,更好的是,您应该直接使用C ++中的NumPy数组作为指向Nx4x2数组的指针。换句话说,不必要地停止复制数据,但如果有必要,复制到固定的Nx4x2结构而不是NxMx2,这很慢。

答案 1 :(得分:0)

通过明确初始化向量的每个元素,我赢得了100倍的速度。确实有一个cython -a它现在有0个黄线。

cdef int N=200000 #Of this order of magnitude
cdef np.ndarray[DTYPE_t,ndim=3] numpy_array=np.random.uniform(size=(N,4,2))
t1=time.time()
cdef vector[vector[pair[double,double]]] c_structure
cdef vector[pair[double,double]] empty_vector, vector
cdef pair[double,double] a1, a2, a3, a4
c_structure.reserve(N)
cdef int i
for i in range(N):
  a1.first=numpy_array[i,0,0]
  a1.second=numpy_array[i,0,1]
  a2.first=numpy_array[i,1,0]
  a2.second=numpy_array[i,1,1]
  a3.first=numpy_array[i,2,0]
  a3.second=numpy_array[i,2,1]
  a4.first=numpy_array[i,3,0]
  a4.second=numpy_array[i,3,1]
  vector.push_back(a1)
  vector.push_back(a2)
  vector.push_back(a3)
  vector.push_back(a4)
  c_structure.push_back(vector)
  vector=empty_vector
t2=time.time()

0.036s而不是3s