【发布时间】:2018-02-14 12:11:15
【问题描述】:
我最近使用 Numpy 将 MATLAB 脚本转换为 Python,发现它的运行速度明显变慢。我期望类似的性能,所以我想知道我是否做错了什么。
作为简化示例,我手动对几何级数求和:
MATLAB 版本:
function s = array_sum(a, array_size, iterations)
s = zeros(array_size);
for m = 1:iterations
s = a + 0.5*s;
end
end
% benchmark code
array_size = 500
iterations = 500
a = randn(array_size)
f = @() array_sum(a, array_size, iterations);
fprintf('run time: %.2f ms\n', timeit(f)*1e3);
Python/Numpy 版本:
import numpy as np
import timeit
def array_sum(a, array_size, iterations):
s = np.zeros((array_size, array_size))
for m in range(iterations):
s = a + 0.5*s
return s
array_size = 500
iterations = 500
a = np.random.randn(array_size, array_size)
timeit_iterations = 10
t1 = timeit.timeit(lambda: array_sum(a, array_size, iterations),
number=timeit_iterations)
print("run time: {:.2f} ms".format(1e3*t1/timeit_iterations))
在我的机器上,MATLAB 在 58 毫秒内完成。 Python 版本的运行时间为 292 毫秒,或者慢了 5 倍。
我还尝试通过添加 Numba JIT 装饰器 @jit('f8[:,:](i8, i8)', nopython=True) 来加速 Python 代码,但时间仅下降到 236 毫秒(慢 4 倍)。
这比我预期的要慢。我是否不正确地使用 timeit?我的 Python 代码有问题吗?
编辑:编辑以便在基准函数之外创建随机矩阵。
编辑 2:我使用 Torch 而不是 Numpy 运行基准测试(计算总和为 s = torch.add(s, 0.5, a)),它在我的计算机上运行仅 52 毫秒!
【问题讨论】:
-
你有
nopython=True,但你不是在那里使用 NumPy 函数吗? -
@Divakar 我认为最近的 numba 版本支持一些数组分配功能。 @ LorenzForvang 你的测试只执行元素操作,据我所知,这些操作在 BLAS 中没有实现(这并不是说它们在 numpy 中应该更慢)。
-
@Divakar 是的,我在那里使用 NumPy 函数。此页面 (numba.pydata.org/numba-doc/dev/reference/numpysupported.html) 列出了 Numba 在 nopython 模式下支持的许多 NumPy 函数。但是无论我将
nopython设置为 True 还是 False,运行时间都是相同的。 -
@kazemakase 好点!我删除了对 BLAS 的引用
-
顺便说一句,有趣的事实:我更改了迭代以在 Matlab 中执行矩阵点积
s = r * s和在 Python 中执行s = r @ s。 Matlab 仍然更快,但只有 1.5 倍。
标签: python arrays matlab performance numpy