Python 使用 numpy 最小值、最大值(或 numba)进行优化
Python optimization with numpy min, max (or numba)
我需要使用 python、numpy 进行性能优化。
我的数据是这样的,
a1 = np.array(np.random.random(500000) * 1000)
a2 = np.array(np.random.random(500000) * 5000)
对于不同的 ndarray a1、a2,我想计算最小-最大差距。
numpy:
np.max(a1) - np.min(a2)
numba:
@nb.jit(nb.float64(nb.float64, nb.float64), cache=True, fastmath=True)
def nb_max_min(s1, s2):
return np.max(s1) - np.min(s2)
但是,结果让我很失望
min-max(numba): 1.574092000000249 ms
max-max(numpy): 1.4246419999999205 ms
如果可能的话,我想在 ~0.xx 毫秒内进行更快速的计算。
如何攻克这个优化?
更新
我只测量了最大 - 最小部分。我的计时代码在这里。
import time
def timing(label, fn):
t0 = time.perf_counter()
fn()
t1 = time.perf_counter()
print('{}: {} ms'.format(label, (t1 - t0) * 1000))
我所有的代码都在这里,
@nb.jit(nb.float64(nb.float64, nb.float64), cache=True, fastmath=True)
def nb_max_min(s1, s2):
return np.max(s1) - np.min(s2)
a1 = np.random.random(periods) * 2000
a2 = np.random.random(periods) * 1000
timing('nb_min_max', lambda: nb_max_min(a1, a2))
timing('nb_min_max', lambda: nb_max_min(a1, a2))
timing('nb_min_max', lambda: nb_max_min(a1, a2))
timing('max-max', lambda: np.max(a1) - np.min(a2))
timing('max-max', lambda: np.max(a1) - np.min(a2))
timing('max-max', lambda: np.max(a1) - np.min(a2))
而且,这是结果
nb_min_max: 0.728947999999896 ms
nb_min_max: 1.0030130000000526 ms
nb_min_max: 1.3124690000001493 ms
max-max: 1.662436000000156 ms
max-max: 0.9315169999997153 ms
max-max: 1.9570019999992638 ms
我也试过 timeit
%timeit np.max(a1) - np.min(a2)
475 µs ± 9.72 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
我认为这是 python 最快的方法。 Numpy 或 numba 的结果没有显着差异。正如user2699评论的那样,fortran是最后一次优化的机会..
使用 ipython 中的“%timeit”魔法,我得到了以下结果:
数组生成:
%%timeit
a1 = np.array(np.random.random(500000) * 1000)
a2 = np.array(np.random.random(500000) * 5000)
% 23.3 ms
最小-最大差距:
%%timeit
np.max(a1) - np.min(a2)
% 444 µs
我认为这已经非常快了,也许您测量了一些额外的开销,就像@juvian 建议的那样?
你是如何得到这些非常慢的时间的?
代码
import numba as nb
import numpy as np
import time
a1 = np.array(np.random.random(500000) * 1000)
a2 = np.array(np.random.random(500000) * 5000)
@nb.jit(nb.float64(nb.float64[:], nb.float64[:]),parallel=True,fastmath=True)
def nb_max_min(s1, s2):
return np.max(s1) - np.min(s2)
def np_max_min(s1,s2):
return np.max(s1) - np.min(s2)
t1=time.time()
for i in range(10000):
res_1=np_max_min(a1, a2)
print(str((time.time()-t1)/10)+ ' ms')
t1=time.time()
for i in range(10000):
res_2=nb_max_min(a1, a2)
print(str((time.time()-t1)/10)+ ' ms')
np.allclose(res_1,res_2)
结果
Numpy: 0.298ms (=26.8 GB/s)
Numba: 0.243ms (=33 GB/s)
讨论
这个简单的操作是内存有限的。最大。我的 Core i7-4th gen 的内存吞吐量是 25.6GB/s。由于缓存效应,Numba 甚至显着超过了内存带宽(问题或多或少出现在 L3 缓存中)。实际代码中的时间可能会更低,因为输入数组可能不在 L3 缓存中。
我需要使用 python、numpy 进行性能优化。
我的数据是这样的,
a1 = np.array(np.random.random(500000) * 1000)
a2 = np.array(np.random.random(500000) * 5000)
对于不同的 ndarray a1、a2,我想计算最小-最大差距。
numpy:
np.max(a1) - np.min(a2)
numba:
@nb.jit(nb.float64(nb.float64, nb.float64), cache=True, fastmath=True)
def nb_max_min(s1, s2):
return np.max(s1) - np.min(s2)
但是,结果让我很失望
min-max(numba): 1.574092000000249 ms
max-max(numpy): 1.4246419999999205 ms
如果可能的话,我想在 ~0.xx 毫秒内进行更快速的计算。 如何攻克这个优化?
更新
我只测量了最大 - 最小部分。我的计时代码在这里。
import time
def timing(label, fn):
t0 = time.perf_counter()
fn()
t1 = time.perf_counter()
print('{}: {} ms'.format(label, (t1 - t0) * 1000))
我所有的代码都在这里,
@nb.jit(nb.float64(nb.float64, nb.float64), cache=True, fastmath=True)
def nb_max_min(s1, s2):
return np.max(s1) - np.min(s2)
a1 = np.random.random(periods) * 2000
a2 = np.random.random(periods) * 1000
timing('nb_min_max', lambda: nb_max_min(a1, a2))
timing('nb_min_max', lambda: nb_max_min(a1, a2))
timing('nb_min_max', lambda: nb_max_min(a1, a2))
timing('max-max', lambda: np.max(a1) - np.min(a2))
timing('max-max', lambda: np.max(a1) - np.min(a2))
timing('max-max', lambda: np.max(a1) - np.min(a2))
而且,这是结果
nb_min_max: 0.728947999999896 ms
nb_min_max: 1.0030130000000526 ms
nb_min_max: 1.3124690000001493 ms
max-max: 1.662436000000156 ms
max-max: 0.9315169999997153 ms
max-max: 1.9570019999992638 ms
我也试过 timeit
%timeit np.max(a1) - np.min(a2)
475 µs ± 9.72 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
我认为这是 python 最快的方法。 Numpy 或 numba 的结果没有显着差异。正如user2699评论的那样,fortran是最后一次优化的机会..
使用 ipython 中的“%timeit”魔法,我得到了以下结果:
数组生成:
%%timeit
a1 = np.array(np.random.random(500000) * 1000)
a2 = np.array(np.random.random(500000) * 5000)
% 23.3 ms
最小-最大差距:
%%timeit
np.max(a1) - np.min(a2)
% 444 µs
我认为这已经非常快了,也许您测量了一些额外的开销,就像@juvian 建议的那样?
你是如何得到这些非常慢的时间的?
代码
import numba as nb
import numpy as np
import time
a1 = np.array(np.random.random(500000) * 1000)
a2 = np.array(np.random.random(500000) * 5000)
@nb.jit(nb.float64(nb.float64[:], nb.float64[:]),parallel=True,fastmath=True)
def nb_max_min(s1, s2):
return np.max(s1) - np.min(s2)
def np_max_min(s1,s2):
return np.max(s1) - np.min(s2)
t1=time.time()
for i in range(10000):
res_1=np_max_min(a1, a2)
print(str((time.time()-t1)/10)+ ' ms')
t1=time.time()
for i in range(10000):
res_2=nb_max_min(a1, a2)
print(str((time.time()-t1)/10)+ ' ms')
np.allclose(res_1,res_2)
结果
Numpy: 0.298ms (=26.8 GB/s)
Numba: 0.243ms (=33 GB/s)
讨论
这个简单的操作是内存有限的。最大。我的 Core i7-4th gen 的内存吞吐量是 25.6GB/s。由于缓存效应,Numba 甚至显着超过了内存带宽(问题或多或少出现在 L3 缓存中)。实际代码中的时间可能会更低,因为输入数组可能不在 L3 缓存中。