【发布时间】:2018-10-16 19:14:12
【问题描述】:
我有一个问题,我必须使用自定义函数对一个非常大的数组(形状 - 7900000X4X4)进行排序。我用了sorted,但排序花了1个多小时。我的代码是这样的。
def compare(x,y):
print('DD '+str(x[0]))
if(np.array_equal(x[1],y[1])==True):
return -1
a = x[1].flatten()
b = y[1].flatten()
idx = np.where( (a>b) != (a<b) )[0][0]
if a[idx]<0 and b[idx]>=0:
return 0
elif b[idx]<0 and a[idx]>=0:
return 1
elif a[idx]<0 and b[idx]<0:
if a[idx]>b[idx]:
return 0
elif a[idx]<b[idx]:
return 1
elif a[idx]<b[idx]:
return 1
else:
return 0
def cmp_to_key(mycmp):
class K:
def __init__(self, obj, *args):
self.obj = obj
def __lt__(self, other):
return mycmp(self.obj, other.obj)
return K
tblocks = sorted(tblocks.items(),key=cmp_to_key(compare))
这很有效,但我希望它在几秒钟内完成。我认为 python 中的任何直接实现都不能给我所需的性能,所以我尝试了 cython。我的 Cython 代码是这样的,非常简单。
cdef int[:,:] arrr
cdef int size
cdef bool compare(int a,int b):
global arrr,size
cdef int[:] x = arrr[a]
cdef int[:] y = arrr[b]
cdef int i,j
i = 0
j = 0
while(i<size):
if((j==size-1)or(y[j]<x[i])):
return 0
elif(x[i]<y[j]):
return 1
i+=1
j+=1
return (j!=size-1)
def sorted(np.ndarray boxes,int total_blocks,int s):
global arrr,size
cdef int i
cdef vector[int] index = xrange(total_blocks)
arrr = boxes
size = s
sort(index.begin(),index.end(),compare)
return index
cython 中的这段代码耗时 33 秒! Cython 是解决方案,但我正在寻找一些可以直接在 python 上运行的替代解决方案。例如麻木。我尝试了 Numba,但没有得到令人满意的结果。请帮忙!
【问题讨论】:
-
如果你想让我们做的不仅仅是阅读代码,你需要提供一些测试数据。
items方法表明tblocks是一个字典。这些值是某种类型和/或维度的数组? -
dtype是什么数组?此外,对我来说,您的 Python 和 Cython 比较函数如何等效并不明显。 -
我想知道是否有使用值而不是 cmp 的等效方法。
-
那么 box 真的是一个 (7900000X4X4) 数组吗?你能提供一个最小的工作示例吗?这应该是使用自定义排序功能的方法:github.com/numba/numba/blob/master/numba/targets/quicksort.py
标签: python performance sorting numpy cython