我花了几周的时间将我的cython代码更改为纯C(尽管仍在Cython中)以获得速度并能够移除GIL以进行多线程以获得更高的速度。
在stackoverflow用户的帮助下,我终于成功并获得了一个因子10纯C vs cython与一些python然后通过使用4个线程(prange)在double for循环我的部分代码。
但是为了进入这个循环,我首先必须转换维度(N,4,2)(和(K,4,2))的两个3维numpy ndarrays
来vector[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)!
我做错了什么?!如何加快这个速度?!
答案 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