比较Numpy和Matlab数组求和速度

Lor*_*ang 12 python arrays performance matlab numpy

我最近使用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);
Run Code Online (Sandbox Code Playgroud)

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))
Run Code Online (Sandbox Code Playgroud)

在我的机器上,MATLAB在58毫秒内完成.Python版本运行时间为292毫秒,或慢5倍.

我还尝试通过添加Numba JIT装饰器来加速Python代码@jit('f8[:,:](i8, i8)', nopython=True),但时间仅降至236毫秒(慢4倍).

这比我想象的要慢.我不正确地使用timeit吗?我的Python代码有问题吗?

编辑:编辑,以便在基准函数之外创建随机矩阵.

编辑2:我使用Torch而不是Numpy运行基准测试(计算总和为s = torch.add(s, 0.5, a)),它在我的计算机上仅运行52毫秒!

hpa*_*ulj 0

时间包括randn调用和求和:

\n\n
In [68]: timeit array_sum(array_size, 0)\n16.6 ms \xc2\xb1 436 \xc2\xb5s per loop (mean \xc2\xb1 std. dev. of 7 runs, 100 loops each)\nIn [69]: timeit array_sum(array_size, 1)\n18.9 ms \xc2\xb1 293 \xc2\xb5s per loop (mean \xc2\xb1 std. dev. of 7 runs, 100 loops each)\nIn [70]: timeit array_sum(array_size, 20)\n55.5 ms \xc2\xb1 131 \xc2\xb5s per loop (mean \xc2\xb1 std. dev. of 7 runs, 10 loops each)\nIn [71]: (55-16)/20\nOut[71]: 1.95\n
Run Code Online (Sandbox Code Playgroud)\n\n

因此,设置时间为 16 毫秒,每次迭代时间为 2 毫秒。相同的模式,迭代 500 次。

\n\n

MATLAB 执行一些 JIT 编译。我不知道这里是不是这样。我没有 MATLAB 来测试。八度音程(无timeit

\n\n
>> t = time(); array_sum(500,0); (time()-t)*1000\nans =  13.704\n>> t = time(); array_sum(500,1); (time()-t)*1000\nans =  16.219\n>> t = time(); array_sum(500,20); (time()-t)*1000\nans =  82.346\n>> t = time(); array_sum(500,500); (time()-t)*1000\nans =  1610.6\n
Run Code Online (Sandbox Code Playgroud)\n\n

Octave 的random速度更快,但每次迭代总和更慢。

\n