PythonとJuliaの速度の比較


9

私はこれら2つのスニペットを比較して、1秒間にいくつの反復を実行できるかを確認しようとしました。Juliaは250万回の反復を達成し、Python 400万回を達成したことがわかりました。ジュリアはもっと速くなるはずではありません。または、これらの2つのスニペットは同等ではないでしょうか?

Python:

t1 = time.time()
i = 0
while True:
    i += 1
    if time.time() - t1 >= 1:
        break

ジュリア:

function f()
    i = 0
    t1 = now()
    while true
        i += 1
        if now() - t1 >= Base.Dates.Millisecond(1000)
            break
        end
    end
    return i
end

4
Juliaがどのように機能するかはわかりませんが、Pythonが単純な整数比較を行っている間は、比較するたびに新しいオブジェクトを作成する必要があるようです。
chepner

1
また、これは貧しい人のスピード比較だと思いませんか?今日では、PythonとJuliaを適切なモチベーション(両端で)でほぼ同じ速度で実行できます。どちらかの言語を選択するためにこれを実行している場合は、どちらの言語を使用するかを検討してください。実際に必要になったときに、後で最適化できます。
norok2

@ norok2これは一部のコードには当てはまりますが、他のコードには当てはまりません。Pythonコードを高速言語で記述されたライブラリ関数の呼び出しに変換できる場合、またはそれがnumbaなどでサポートされている場合は、多分、そうでなければPythonが大幅に遅くなります。
DNF

@DNF Pythonが高速なものとJuliaが高速なものがあります。両方の例を見つけることができると思います。比較的高価な明示的なループと関数呼び出しのために、Pythonが「大幅に」(意味が何であれ)遅くなると言っても、全体像を過度に無視しています。確かに、もしそれがあなたの仕事の馬なら、多分あなたはジュリアと一緒にいる方がよいでしょう。ただし、適切なツールを使用すれば、Pythonでも同等の速度が得られます。これらのツールを学ぶ価値はありますか、それとも別の言語を学ぶ方が良いですか。言うのは難しいです。
norok2

1
私は両方の言語を使用しており、両方がより高速であるという「いくつかの」例はありますが、バランスは一方的にかなりです。これは単にPythonが解釈され、パフォーマンスにほとんど焦点を合わせていない結果ですが、ジュリアはパフォーマンスに重点を置いています。実際、PythonはCと同じくらい高速であると言っているのとよく似ています。大きな違いなければ、奇妙であり、Juliaの目的の多くを損なうことになります。
DNF

回答:


9

これは、通常、実体の計算にかかる時間を測定するものであり、特定の時間内にいくつの自明な反復を実行できるかを確認するのではないため、一種の奇妙なパフォーマンス比較です。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
}

コンパイラーはループを見て、結果が毎回同じであることを理解し、実際にループを実行する代わりにその定数値を返します。もちろん、これには時間がかかりません。


これはプログラミング言語のBogoMipsです
norok2

1
そうです、しかしbogomipsは、プログラミング言語ではなく、CPUの測定に使用されます。しかし、確かに、それは人が測定できるものです。
StefanKarpinski

4

おそらくtime_nsJuliaで関数を使いたいでしょう:

function f()
    i = 0
    t1 = time_ns()
    while true
        i += 1
        if time_ns() - t1 >= 10^9
            break
        end
    end
    return i
end

私のコンピューターでは、Pythonの10倍の速度で実行されます。


4

まあ、それは私のシステムで観察するものではありません:

Python 3.7.7

Python 3.7.7 (default, Mar 26 2020, 15:48:22) 
Type 'copyright', 'credits' or 'license' for more information
IPython 7.4.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import time                                                                                                                                                       

In [2]: def f(): 
   ...:     t1 = time.time() 
   ...:     i = 0 
   ...:     while True: 
   ...:         i += 1 
   ...:         if time.time() - t1 >= 1: 
   ...:             return i 
   ...:                                                                                                                                                                   

In [3]: f()                                                                                                                                                               
Out[3]: 4676268


ジュリア1.4.0:

julia> using Dates

julia> function f()
           i = 0
           t1 = now()
           while true
               i += 1
               if now() - t1 >= Dates.Millisecond(1000)
                   break
               end
           end
           return i
       end
f (generic function with 1 method)

julia> f()
6339528

ただし、単に使用するtime(つまり、単純な数値を比較する)方がさらに高速です。

julia> function f()
           i = 0
           t1 = time()
           while true
               i += 1
               if time() - t1 >= 1
                   break
               end
           end
           return i
       end
f (generic function with 1 method)

julia> f()
24742703

time.perf_counter_ns()Pythonでは使用しないでください。
norok2

time.perf_counter_nsを使用しても、このベンチマークでは(少なくとも私のシステムでは)何も変更されません。1秒程度の時間差を計測する場合、時間計測の精度はあまり問題にならないと思います。ここで問題になるのは、測定を実行して結果のオブジェクトを比較するのにかかる時間だけです(ループ自体の効率も同様です)。
フランソワ・Févotte

ジュリアでは測定時間が重要です-私のコードではそれよりも30%速いので使用しtime_nsませんでしたtime
BogumiłKAMINSKI
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.