我担心以下功能的速度:
def cch(tau):
return np.sum(abs(-1*np.diff(cartprod)-tau)<0.001)
"cartprod"
是列表的变量,如下所示:
cartprod = np.ndarray([[0.0123,0.0123],[0.0123,0.0459],...])
此列表的长度约为2500万。基本上,我正在尝试找到一种更快的方法来为该np.ndarray
中的每个配对列表返回差异列表。有没有比np.diff
更快的算法方式或功能?或者,np.diff
结束了吗?我也欢迎其他任何人。
编辑:谢谢大家的解决方案!
答案 0 :(得分:3)
在array-slicing
的帮助下,我们可以利用multi-core
with numexpr
module处理大数据并提高内存效率,从而提高性能。
import numexpr as ne
def cch_numexpr(a, tau):
d = {'a0':a[:,0],'a1':a[:,1]}
return np.count_nonzero(ne.evaluate('abs(a0-a1-tau)<0.001',d))
对25M
大小的数据进行采样运行和计时-
In [83]: cartprod = np.random.rand(25000000,2)
In [84]: cch(cartprod, tau=0.5) == cch_numexpr(cartprod, tau=0.5)
Out[84]: True
In [85]: %timeit cch(cartprod, tau=0.5)
10 loops, best of 3: 150 ms per loop
In [86]: %timeit cch_numexpr(cartprod, tau=0.5)
10 loops, best of 3: 25.5 ms per loop
加速6x
。
这是8
个线程。因此,随着更多线程可用于计算,它应该进一步改进。 Related post
了解如何控制多核功能。
答案 1 :(得分:3)
我认为您正在通过反复返回多个长度约为2500万的np.array而不是缓慢的np.diff来碰壁。我写了一个等效的函数,它遍历数组并计算结果。该功能需要使用numba进行快速同步。我希望这是可以接受的。
arr = np.random.rand(25000000, 2)
def cch(tau, cartprod):
return np.sum(abs(-1*np.diff(cartprod)-tau)<0.001)
%timeit cch(0.01, arr)
@jit(nopython=True)
def cch_jit(tau, cartprod):
count = 0
tau = -tau
for i in range(cartprod.shape[0]):
count += np.less(np.abs(tau - (cartprod[i, 1]- cartprod[i, 0])), 0.001)
return count
%timeit cch_jit(0.01, arr)
产生
294 ms ± 2.82 ms
42.7 ms ± 483 µs
大约快6倍。
答案 2 :(得分:1)
出于好奇,我比较了@Divakar numexpr和@alexdor numba.jit的解决方案。 numexpr.evaluate
的实现似乎是使用numba
的jit编译器的两倍。显示了每次运行100次的结果:
np.sum: 111.07543396949768
numexpr: 12.282189846038818
JIT: 6.2505223751068115
'np.sum' returns same result as 'numexpr'
'np.sum' returns same result as 'jit'
'numexpr' returns same result as 'jit'
脚本,以便再现结果:
import numpy as np
import time
import numba
import numexpr
arr = np.random.rand(25000000, 2)
runs = 100
def cch(tau, cartprod):
return np.sum(abs(-1*np.diff(cartprod)-tau)<0.001)
def cch_ne(tau, cartprod):
d = {'a0':cartprod[:,0],'a1':cartprod[:,1], 'tau': tau}
count = np.count_nonzero(numexpr.evaluate('abs(a0-a1-tau)<0.001',d))
return count
@numba.jit(nopython=True)
def cch_jit(tau, cartprod):
count = 0
tau = -tau
for i in range(cartprod.shape[0]):
count += np.less(np.abs(tau - (cartprod[i, 1]- cartprod[i, 0])), 0.001)
return count
start = time.time()
for x in range(runs):
x1 = cch(0.01, arr)
print('np.sum:\t\t', time.time() - start)
start = time.time()
for x in range(runs):
x2 = cch_ne(0.01, arr)
print('numexpr:\t', time.time() - start)
x3 = cch_jit(0.01, arr)
start = time.time()
for x in range(runs):
x3 = cch_jit(0.01, arr)
print('JIT:\t\t', time.time() - start)
if x1 == x2: print('\'np.sum\' returns same result as \'numexpr\'')
if x1 == x3: print('\'np.sum\' returns same result as \'jit\'')
if x2 == x3: print('\'numexpr\' returns same result as \'jit\'')