有效地计算数组中 N 个最小数字的总和
Efficiently compute sum of N smallest numbers in an array
我有一个代码,首先我需要对值进行排序,然后我需要对前 10 个元素求和。我很想使用 Numba 包来加快 运行 时间,但它不起作用,Numba 使代码比 Numpy 慢。
第一次测试,求和:
import numpy as np
import numba
np.random.seed(0)
def SumNumpy(x):
return np.sum(x[:10])
@numba.jit()
def SumNumpyNumba(x):
return np.sum(x[:10])
我的测试:
x = np.random.rand(1000000000)
%timeit SumNumpy(x)
%timeit SumNumpyNumba(x)
结果:
100000 次循环,最好的 3 次:每次循环 6.8 微秒
1000000 次循环,最好的 3 次:每次循环 715 ns
没关系,Numba 做得很好。但是当我一起尝试 np.sort 和 np.sum:
def sumSortNumpy(x):
y = np.sort(x)
return np.sum(y[:10])
@numba.jit()
def sumSortNumpyNumba(x):
y = np.sort(x)
return np.sum(y[:10])
并测试:
x = np.random.rand(100000)
%timeit sumSortNumpy(x)
%timeit sumSortNumpyNumba(x)
结果:
100 个循环,3 个循环中的最佳:每个循环 14.6 毫秒
10 个循环,3 个循环中的最佳:每个循环 20.6 毫秒
Numba/Numpy 比 Numpy 慢。所以我的问题是我们是否可以改进功能 "sumSortNumpyNumba"?
感谢帮助。
谢谢。
我们在排序后求和,因此前 N=10
个元素的顺序无关紧要。因此,我们可以使用 np.argpartition
来避免排序步骤,并简单地为我们提供第一个 N
最小数字的组,这些数字可以在以后求和,就像这样 -
def sumSortNumPyArgpartition(x, N=10):
return x[np.argpartition(x, N)[:N]].sum()
各种数据集的计时 -
In [39]: np.random.seed(0)
...: x = np.random.rand(1000000)
In [40]: %timeit sumSortNumpy(x)
...: %timeit sumSortNumPyArgpartition(x)
10 loops, best of 3: 78.6 ms per loop
100 loops, best of 3: 12.3 ms per loop
In [41]: np.random.seed(0)
...: x = np.random.rand(10000000)
In [42]: %timeit sumSortNumpy(x)
...: %timeit sumSortNumPyArgpartition(x)
1 loop, best of 3: 920 ms per loop
10 loops, best of 3: 153 ms per loop
In [43]: np.random.seed(0)
...: x = np.random.rand(100000000)
In [44]: %timeit sumSortNumpy(x)
...: %timeit sumSortNumPyArgpartition(x)
1 loop, best of 3: 10.6 s per loop
1 loop, best of 3: 978 ms per loop
我有一个代码,首先我需要对值进行排序,然后我需要对前 10 个元素求和。我很想使用 Numba 包来加快 运行 时间,但它不起作用,Numba 使代码比 Numpy 慢。
第一次测试,求和:
import numpy as np
import numba
np.random.seed(0)
def SumNumpy(x):
return np.sum(x[:10])
@numba.jit()
def SumNumpyNumba(x):
return np.sum(x[:10])
我的测试:
x = np.random.rand(1000000000)
%timeit SumNumpy(x)
%timeit SumNumpyNumba(x)
结果:
100000 次循环,最好的 3 次:每次循环 6.8 微秒
1000000 次循环,最好的 3 次:每次循环 715 ns
没关系,Numba 做得很好。但是当我一起尝试 np.sort 和 np.sum:
def sumSortNumpy(x):
y = np.sort(x)
return np.sum(y[:10])
@numba.jit()
def sumSortNumpyNumba(x):
y = np.sort(x)
return np.sum(y[:10])
并测试:
x = np.random.rand(100000)
%timeit sumSortNumpy(x)
%timeit sumSortNumpyNumba(x)
结果:
100 个循环,3 个循环中的最佳:每个循环 14.6 毫秒
10 个循环,3 个循环中的最佳:每个循环 20.6 毫秒
Numba/Numpy 比 Numpy 慢。所以我的问题是我们是否可以改进功能 "sumSortNumpyNumba"?
感谢帮助。
谢谢。
我们在排序后求和,因此前 N=10
个元素的顺序无关紧要。因此,我们可以使用 np.argpartition
来避免排序步骤,并简单地为我们提供第一个 N
最小数字的组,这些数字可以在以后求和,就像这样 -
def sumSortNumPyArgpartition(x, N=10):
return x[np.argpartition(x, N)[:N]].sum()
各种数据集的计时 -
In [39]: np.random.seed(0)
...: x = np.random.rand(1000000)
In [40]: %timeit sumSortNumpy(x)
...: %timeit sumSortNumPyArgpartition(x)
10 loops, best of 3: 78.6 ms per loop
100 loops, best of 3: 12.3 ms per loop
In [41]: np.random.seed(0)
...: x = np.random.rand(10000000)
In [42]: %timeit sumSortNumpy(x)
...: %timeit sumSortNumPyArgpartition(x)
1 loop, best of 3: 920 ms per loop
10 loops, best of 3: 153 ms per loop
In [43]: np.random.seed(0)
...: x = np.random.rand(100000000)
In [44]: %timeit sumSortNumpy(x)
...: %timeit sumSortNumPyArgpartition(x)
1 loop, best of 3: 10.6 s per loop
1 loop, best of 3: 978 ms per loop