为什么 Julia 比 MATLAB 慢?

Ako*_*kon 1 julia

我刚刚编写了这个非常简单的函数来测试 Julia 和 MATLAB 的性能。我只是注意到 MATLAB 中的执行时间要短得多。这是简单的代码:

MATLAB:

tic

aa = 0;

for loop =1:1e6

       aa = aa+loop;

end

toc
Run Code Online (Sandbox Code Playgroud)

经过的时间是 0.004628 秒。

朱莉娅:

function sum_test(a)

    for i = 1:1e6
        a = a + i
    end

    return a
end
Run Code Online (Sandbox Code Playgroud)

经过的时间是 0.093886155s:93 毫秒。

我还在 Julia 中编写了一个函数来避免使用全局变量,这提高了性能,但它仍然比 MATLAB 慢得多。有人可以帮我理解这一点吗?

Col*_*ers 10

如果不了解您如何为 Julia 代码计时,就不可能说出来。然而,最可能的解释是您同时计时编译时间和执行时间。Julia 和 MatLab 编译器的行为完全不同。当您在 Julia 中编写新函数时,它会在您第一次使用时编译。因此,它的第一次执行会很慢,但所有后续调用都很快。为了解决这个问题,如果您正在对 Julia 进行基准测试,建议您使用该BenchmarkTools包。在我的(不是特别特别的)机器上:

function sum_test(a)
    for i = 1:1e6
        a = a + i
    end
    return a
end
using BenchmarkTools
@btime sum_test(1)
Run Code Online (Sandbox Code Playgroud)

产生以下输出:

julia> @btime sum_test(1)
  2.135 ms (0 allocations: 0 bytes)
Run Code Online (Sandbox Code Playgroud)

所以大约 2 毫秒,大约是您的 MatLab 运行速度的两倍。

但我们能做得更好吗?我们当然可以。MatLab 倾向于将所有数字视为双精度浮点数,因此在 MatLab 中编码时不会过多考虑数字的类型。在 Julia 中,情况并非如此。在此示例中,您已将循环的上限指定为1e6。注意:

julia> typeof(1e6)
Float64
Run Code Online (Sandbox Code Playgroud)

啊哈!您可能不Float64希望循环变量是 a ,而是希望它是一个整数。那么当我们改变它时会发生什么?尝试运行这个:

function sum_test(a)
    for i = 1:1000000
        a = a + i
    end
    return a
end
using BenchmarkTools
@btime sum_test(1)
Run Code Online (Sandbox Code Playgroud)

现在输出:

julia> @btime sum_test(1)
  1.208 ns (0 allocations: 0 bytes)
Run Code Online (Sandbox Code Playgroud)

是的,你没有看错。它花了 1.2 纳秒,或者比 MatLab 快大约 6 个数量级。

那么发生了什么?在循环上限是整数的情况下,Julia 编译器足够聪明,可以意识到它实际上并不需要运行循环来正确计算结果。由于正在执行的算法的性质,可以使用编译器为您完成的单个公式来确定答案。换句话说,Julia 编译器优化了整个循环!

  • `@btime` 多次运行您的函数(可能数千次),并计算统计数据。`tic`/`toc` 不适合测量非常短的函数的执行时间,因为测量结果会非常嘈杂,并且还可能包括编译时间、偶尔的操作系统故障或垃圾收集。因此,不要使用`tic`/`toc`或`@time`来测量短函数的执行时间,使用`@btime`或`@benchmark`。Matlab 和 Python 也是一样:不要使用 `tic`/`toc`,使用 `timeit` 函数,该函数与 `@btime` 类似。 (2认同)