LoginSignup
5
0

More than 3 years have passed since last update.

Julia の速度

Posted at

Juliaの実行速度がどのくらい速いのか、簡単なループで計測してみた。やっていることはランダムに作った倍精度浮動小数点数100万個を加算するだけだ。

Juliaのコード

Juliaのコードはこんなかんじ。

randoms = rand(1000000)

function mysum(v)
    sum = 0
    for i in v
        sum += i
    end    
end

using BenchmarkTools
mysum(randoms)
@benchmark mysum($randoms)

benchmarkを取る前に一度空振りしているのはJITコンパイルさせるため。

Pythonのコード

Pythonのほうも一応速度を意識してインデックスで回してみた。イテレータでやるよりは速いはず。

import random
import time

SIZE = 1000000
randoms = [random.random() for _ in range(SIZE)]

def mysum(v):
    sum = 0.0
    for i in range(len(v)):
        sum += v[i]
    return sum

now = time.time()
mysum(randoms)
then = time.time()

print (then - now)

Cのコード

Cはこんな感じ。Cで時間を測定する正しい方法がよくわからないけど、もう少しまともなライブラリはないのだろうか。2019年だぞ。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>

#define VECSIZE 1000000
int main(){
    double randoms[VECSIZE];
    for (long i = 0; i < VECSIZE; i++)
        randoms[i] = (double)rand() / RAND_MAX;

    struct timespec now, then;
    clock_gettime(CLOCK_MONOTONIC, &now);

    double sum = 0.0;
    for (long i = 0; i < VECSIZE; i++)
        sum += randoms[i];

    clock_gettime(CLOCK_MONOTONIC, &then);

    double diff = (double)(then.tv_sec - now.tv_sec) +
                  (double)(then.tv_nsec - now.tv_nsec) * 0.000000001;

    printf("%lf: %lf sec.\n", sum, diff);
}

結果

JuliaはBenchmarkツールを使ってちゃんと計測しているが、PythonやCは一回だけなのでちょっと不公平だけど。実行は手元のMacbook Pro。

Julia

julia> include("test.jl")
500387.1306197926
BenchmarkTools.Trial: 
  memory estimate:  0 bytes
  allocs estimate:  0
  --------------
  minimum time:     985.463 μs (0.00% GC)
  median time:      1.005 ms (0.00% GC)
  mean time:        1.024 ms (0.00% GC)
  maximum time:     1.728 ms (0.00% GC)
  --------------
  samples:          4873
  evals/sample:     1

まあ、だいたい1msだと言っていいだろう。

Python

$ python test.py
0.0528540611267

だいたい50msぐらい。

C

$ gcc -O3 test.c; ./a.out; ./a.out
500030.059810: 0.001236 sec.
500030.059810: 0.001252 sec.

1.2ms ぐらい。

まとめ

なんと、この単純なループでは、
JuliaとCがほぼ同じ速度、Pythonは50倍遅いという結果になった。型情報も何もつけていないコードでこの速さというのはさすがにびっくり。予想外。ちなみに、いろいろ型情報をつけたコードで試してみたが、速度は変わらなかった。

Cのアセンブラコード出力を見てみるとループアンローリングもされたそこそこ最適化されたコードになっている。Juliaのコードを@code_nativeで見てみると、アンロールされていない比較的単純なコードになっている。この後ろにLLVMが来て、更に最適化されるのだろうか?

なお、おそろしいことに、Juliaの組み込み関数sumを使うとさらに3−4倍速い。

julia> @benchmark sum($randoms)
BenchmarkTools.Trial: 
  memory estimate:  0 bytes
  allocs estimate:  0
  --------------
  minimum time:     236.386 μs (0.00% GC)
  median time:      267.007 μs (0.00% GC)
  mean time:        272.185 μs (0.00% GC)
  maximum time:     916.661 μs (0.00% GC)
  --------------
  samples:          10000
  evals/sample:     1

こちらのコードを見るとSIMDを使って加算の順番を変えてやっているようだ。

また、組み込みのreduceを使ってもほとんど同じ性能が得られる。すごい。

julia> @benchmark reduce(+, randoms)
BenchmarkTools.Trial: 
  memory estimate:  16 bytes
  allocs estimate:  1
  --------------
  minimum time:     242.448 μs (0.00% GC)
  median time:      289.671 μs (0.00% GC)
  mean time:        300.357 μs (0.00% GC)
  maximum time:     799.867 μs (0.00% GC)
  --------------
  samples:          10000
  evals/sample:     1
5
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
0