【问题标题】:Why doesn't the Julia compiler optimise this loop?为什么 Julia 编译器不优化这个循环?
【发布时间】:2015-01-28 01:58:24
【问题描述】:

我对编译知之甚少,但我惊讶地发现 Julia 编译器没有优化多个进程。

让我们考虑 Julia(这是一个即时编译器),让我们考虑这两个本质上做相同事情的代码。

n=1
@time for i = 1:10^8 n=n+1 end
elapsed time: 3.535394087 seconds (0 bytes allocated)

n=1
@time n=n+10^8
elapsed time: 6.599e-6 seconds (112 bytes allocated)

为什么现代编译器无法理解这个长循环除了将10^8 添加到n 之外什么都不做?

我认为下面的例子更引人注目

n=1
@time for i = 1:10^9 n=n end
elapsed time: 3.496573198 seconds (0 bytes allocated)

【问题讨论】:

  • 这完全取决于编译器的开发人员在优化器中投入了多少精力。实际上,其他语言的一些编译器确实执行该优化。
  • 哦,好的。我预计如何编译代码有一些基本限制。我认为您几乎可以从您的评论中得出答案(最终添加一点解释,说明为什么构建可以执行此优化的编译器是一项艰巨的工作)
  • 这只是一个例子的毫无根据的概括。 -1

标签: compiler-construction compilation julia


【解决方案1】:

这是在全局范围内执行时的一个问题,并且与在类型可能发生变化的条件下进行优化有关,但在适当的情况下,情况会发生变化。将评估限制在函数内允许编译器做更多事情。考虑同样的事情,但在一个函数中。

function f(n::Int64)
   x = 0;
   for i = 1:n
      x = x + 1;
   end
   return x;
end


julia> @time f(100)
elapsed time: 2.93e-6 seconds (80 bytes allocated)
100

julia> @time f(Int64(1e11))
elapsed time: 4.632e-6 seconds (112 bytes allocated)
100000000000

通过使用code_native检查编译器输出,你可以看到循环被优化了

julia> code_native(f,(Int64,)) 

Source line: 6
    push    RBP
    mov RBP, RSP
    test    RDI, RDI
    jg  L15
    xor EDI, EDI
Source line: 6
L15:    mov RAX, RDI 
    pop RBP
    ret

【讨论】:

  • 我理解为什么有人告诉我在 Julia 中将代码行封装到函数中是一种很好的做法。非常感谢您的回答 +1
  • 关于“限制函数内的评估允许编译器做更多事情”的评论。好的,但是为什么呢?好吧,例如,如果n 是一个全局对象,那么其他一些进程或线程或任何可能正在查看它并监视其增长的东西。它也可以代表一个硬件。我对 Julia 一无所知,但在其他一些环境中,您可以在地址空间的特定点声明一个变量,从而将其映射到某个物理设备上。然后不能“优化”写入序列,因为这可能会改变系统的设计行为。
猜你喜欢
  • 2015-05-13
  • 1970-01-01
  • 2021-10-28
  • 2017-01-27
  • 2014-09-28
  • 2018-11-14
  • 1970-01-01
  • 1970-01-01
  • 2012-12-11
相关资源
最近更新 更多