Julia 没有评估该函数吗?

Geo*_*ery 2 julia

我正在研究 Collat​​z 猜想(见下文),并且我有这个函数:

\n
function txpo(max_n)\n    for n \xe2\x88\x88 1:max_n\n        x = n\n        while x \xe2\x89\xa5 n  &&  x != 1\n            x = iseven(x) ? x\xc3\xb72 : 3x+1\n        end\n    end\nend\n
Run Code Online (Sandbox Code Playgroud)\n

我故意不返回任何东西或检查任何东西,以使其尽可能快。天哪,速度快吗... - 实际上太快了,我想。

\n
using BenchmarkTools\n@btime txpo(100_000_000_000_000_000_000_000_000_000_000_000_000)\n\n2.337 ns (0 allocations: 0 bytes)\n
Run Code Online (Sandbox Code Playgroud)\n

运行10^38个while循环只需要2ns?朱莉娅很快,但如果有那么快我会感到惊讶。看起来代码没有被评估。或者我在这里缺少什么?

\n
\n

Collat​​z 猜想\n取一个整数并使用以下规则构建一个级数:如果该数字是偶数除以 2;如果数字是奇数乘以3并加1。猜想:每个系列都会进入循环4-2-1-4

\n

For*_*Bru 5

事实上,整个函数体都被优化了:

\n
julia> function txpo(max_n)\n           for n \xe2\x88\x88 1:max_n\n               x = n\n               while x \xe2\x89\xa5 n  &&  x != 1\n                   x = iseven(x) ? x\xc3\xb72 : 3x+1\n               end\n           end\n       end\ntxpo (generic function with 1 method)\n\njulia> @code_llvm txpo(100000000000)\n;  @ REPL[1]:1 within `txpo`\ndefine void @julia_txpo_179(i64 signext %0) #0 {\ntop:\n;  @ REPL[1]:5 within `txpo`\n  ret void\n}\n
Run Code Online (Sandbox Code Playgroud)\n

如果你使用10^38,这只会更改函数签名以接受 128 位整数。

\n

LLVM IR 代码与以下 Julia 代码基本相同:

\n
julia_txpo_179(_0::Int64) = nothing\n
Run Code Online (Sandbox Code Playgroud)\n

这是完全有道理的,因为为什么要执行一个不返回任何依赖于其计算且没有副作用的函数?

\n

最后,CPU 执行的本机代码实际上是retq“返回调用者”:

\n
julia> @code_native txpo(100000000000)\n    .section    __TEXT,__text,regular,pure_instructions\n; \xe2\x94\x8c @ REPL[1]:5 within `txpo`\n    retq\n    nopw    %cs:(%rax,%rax)\n; \xe2\x94\x94\n\njulia> \n
Run Code Online (Sandbox Code Playgroud)\n

  • “有办法强迫茱莉亚这么做吗?” - 但为什么要这样做呢?无论如何,该函数将始终返回“无”并且不会产生任何副作用。本质上,它没有做任何事情。其结果如何?永远没有结果,只是“什么都没有”。另一方面,如果 Collat​​z 猜想为假,它_永远不会_返回,所以这是一种结果。然而,决定一个函数是否将终止是很困难的(参见“停止问题”),因此 LLVM 显然决定它_将_终止(是的,LLVM 证明了 Collat​​z!)。例如,您可以返回“while”循环终止的次数。 (2认同)