LoginSignup
5
4

More than 3 years have passed since last update.

C++, Go, Julia, Kotlin, Rust, Swift5 で競争

Last updated at Posted at 2020-02-29

計算が速そうな6つの言語で、競争してみた。

種目は、64bit 整数を固定小数点数として使ったマンデルブロ集合の計算。
マシンは MacBook Pro (Retina, 15-inch, Mid 2015)。つまり、x86-64。

ソースコード

全部乗せると長いので、一番短くなった Kotlin のを載せる:

kotlin
fun isMandel(rep: Int, lim: Long, x: Long, y: Long): Boolean {
    var zr = 0L
    var zi = 0L
    for (i in 0 until rep) {
        val zrNext = zr * zr / lim - zi * zi / lim + x
        val ziNext = zr * zi * 2 / lim + y
        val dist2 = zrNext * zrNext / lim + ziNext * ziNext / lim
        if (4 * lim < dist2) {
            return false
        }
        zr = zrNext
        zi = ziNext
    }
    return true
}

fun countMandel(rep: Int, div: Int): Long {
    val lim = 1L.shl(div)
    var count = 0L
    for (y in (-lim)..lim) {
        for (x in (-lim)..lim) {
            if (isMandel(rep, lim, x, y)) {
                count++
            }
        }
    }
    return count
}

fun main(args: Array<String>) {
    val rep = if (args.size <1) 100 else args[0].toInt(10)
    val div = if (args.size <2) 8 else args[1].toInt(10)
    println("rep=$rep  div=$div")
    println("result=${countMandel(rep, div)}")
}

他の言語については https://github.com/nabetani/ml-mandel を参照のこと。

書くにあたって

  • inline 指定はしない(そうしたければコンパイラが勝手にやれ)
  • 型はできるだけちゃんと書く(特に Julia)
  • clang などの -O2 ぐらいの感じで最適化オプションを指定する

ということにした。

C++ と Go 以外はほとんど書いたことがないん言語なんだけど、まあ大丈夫かなと思っている。

各処理系のバージョン

名前 バージョン
clang++ Apple clang version 11.0.0 (clang-1100.0.33.17)
g++ (Homebrew GCC 9.2.0_3) 9.2.0
Go go version go1.13.8 darwin/amd64
Julia julia version 1.1.0
kotlin Kotlin version 1.3.61-release-180 (JRE 12+33)
rustc rustc 1.30.1 (1433507eb 2018-11-07)
Swift5 Apple Swift version 5.1.3 (swiftlang-1100.0.282.1 clang-1100.0.33.15)

測定方法

まずは、引数なしで実行。
その後、 time hoge 1000 9 みたいに実行して、 real の値を拾った。
real を拾ったのは処理系が勝手にマルチスレッドにした場合に備えたもの。まあそんな人いなかったと思うけど。

結果

処理系 処理時間 補足
C++ with clang 5.842秒 バイナリを実行
C++ with gcc 14.842秒 バイナリを実行
Go 15.951秒 バイナリを実行
Julia 7.857秒 time julia main.jl 1000 9 で実行
Kotlin 9.602秒 time kotlin MainKt 1000 9 で実行
Rust 14.822秒 バイナリを実行
Swift5 14.962秒 バイナリを実行

kotlin は、コンパイル済みの class ファイルを kotlin コマンドに渡した。渡されているのは生バイナリじゃないし、kotlin コマンドの起動時間を含んでいるのでハンデがあると思う。

julia は、ソースコードを julia コマンドに渡したのでコンパイル時間を含んでいるかもしれない。コンパイル結果をキャッシュされたりしてるかもしれない(未確認)。いずれにせよ少なくとも julia コマンドの起動時間を含んでいるのでハンデがあると思う。

思ったこと

実行前の予想としては
  速い ← C++勢 < Swift5 ≒ Rust [壁] Julia [壁] Kotlin < Go → 遅い
だったんだけど、
  速い ← clang [壁] Julia < Kotlin [壁] Rust ≒ gcc ≒ Swift5 < Go → 遅い
という意外な結果になった。

clang が速いのは、たぶん lim による除算が全部シフトで行けるとコンパイラにバレたからだと思う(未確認)。
gcc はそれに気づかず、除算命令を発行したんじゃないかな(未確認)。それにしても遅い気がする。

Kotlin と Julia の速さに驚いた。
この内容で gcc を遥かに凌駕するとは。

5
4
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
4