これは、通常、実体の計算にかかる時間を測定するものであり、特定の時間内にいくつの自明な反復を実行できるかを確認するのではないため、一種の奇妙なパフォーマンス比較です。PythonとJuliaのコードを機能させるのに苦労したので、Juliaのコードを機能するように変更しましたが、Pythonコードを実行しませんでした。コメントの@chepnerで述べられているように、オブジェクトとのnow()
時間比較の使用と実行にDateTime
はかなりのコストがかかります。Python time.time()
関数は浮動小数点値を返すだけです。結局のところtime()
、まったく同じことを実行するJulia関数があります。
julia> time()
1.587648091474481e9
これf()
が、私のシステムでの(機能するように変更された)元の関数のタイミングです。
julia> using Dates
julia> function f()
i = 0
t1 = now()
while true
i += 1
if now() - t1 >= Millisecond(1000)
break
end
end
return i
end
f (generic function with 1 method)
julia> f()
4943739
時間が経過する前に、約500万回の反復が行われました。私が言ったように、私はあなたのPythonコードを私のシステムで実行することはできませんでした。しかし、代わりにf()
使用するバージョンは次のとおりです。time()
これを想像的に呼び出しますg()
。
julia> function g()
i = 0
t1 = time()
while true
i += 1
if time() - t1 >= 1
break
end
end
return i
end
g (generic function with 1 method)
julia> g()
36087637
このバージョンは3,600万回の反復を行いました。ジュリアはループが速いと思いますか?わーい!まあ、実際にはこのループの主な作業はtime()
そうするための呼び出しです...ジュリアは多くのtime()
呼び出しを生成するのが速いです!
なぜこれを計るのが奇妙なのですか?言ったように、ここでの実際の作業のほとんどはを呼び出すことtime()
です。ループの残りの部分は実際には何もしません。最適化されたコンパイル済み言語では、コンパイラーが何もしないループを検出すると、それは完全に排除されます。例えば:
julia> function h()
t = 0
for i = 1:100_000_000
t += i
end
return t
end
h (generic function with 1 method)
julia> h()
5000000050000000
julia> @time h()
0.000000 seconds
5000000050000000
うわぁ、ゼロ秒!そんなことがあるものか?さて、LLVMコード(似たようなマシンコードですが、中間表現として使用される架空のマシンの場合)を見てみましょう。
julia> @code_llvm h()
; @ REPL[16]:1 within `h'
define i64 @julia_h_293() {
top:
; @ REPL[16]:6 within `h'
ret i64 5000000050000000
}
コンパイラーはループを見て、結果が毎回同じであることを理解し、実際にループを実行する代わりにその定数値を返します。もちろん、これには時間がかかりません。