2023年9月21日
いただいたコメントに基づき、現在、実験結果の正しさについて確認中です。
これにより今後の編集で結果が変わる可能性があります。

RustとPythonとの3重for文の処理時間を比較してみた

最近、仮想通貨取引所から個人で収集し続けたデータが約1億点になり、
Pythonでは一括での処理が現実的ではなくなってしまいました。
特にfor文を含む処理がネックになっていると思っていて、
numpyやnumbaで何とか置き換えてきたものの、
可読性なども考慮すると限界を感じています。

やむを得ず言語レベルでの変更を検討していたところ、
Rustは書きやすそうで速そうだということで、
一旦Rustの速さを体感したく検証してみました。
(自由にfor文を書きたい…!)

実行環境

Windows11, VSCode
CPU: 11th Gen Intel(R) Core(TM) i7-11800H(論理プロセッサ数: 16)

バージョンRust1.68.0Python3.10.5numba0.56.0

実装

nを引数にとり、3重ループの処理を行う関数fを言語ごとに用意し、nを変えながらそれぞれの処理時間を計測します。

Rust

fn f(n: i64) -> i128 {
    let mut count = 0;
    for i in 0..n {
        for j in 0..i {
            for _ in 0..j {
                count += 1;
            }
        }
    }
    count
}

Python

def f(n):
    count = 0
    for i in range(n):
        for j in range(i):
            for _ in range(j):
                count += 1
    return count

Python + numba

from numba import njit

@njit
def f(n):
    count = 0
    for i in range(n):
        for j in range(i):
            for _ in range(j):
                count += 1
    return count

Python + numba(prange)

すぐにCPU使用率が100%に達します。

from numba import njit, prange

@njit(parallel=True)
def f(n):
    count = 0
    for i in prange(n):
        for j in prange(i):
            for _ in prange(j):
                count += 1
    return count

結果

上記の3重ループでRustとPythonとの処理速度の比較を行った場合、
RustはPythonと比べて桁違いに速いということが分かりました。
同じ時間で計算可能なnの範囲が広がるので、データサイズが大きい場合などに有用だと考えられました。
(rayonなどのクレートを使えばより高速化できる可能性もあります)

Pythonにnumbaを導入した場合でも、Python標準に比べてかなり速くなりますが、
Rustはさらに速かったです。

ただし、Rustをdebugモードでコンパイルした場合の処理時間は速いとは言えず、
簡単な動作確認以外では–releaseオプションをつけてコンパイルしたほうが良さそうです。

n処理時間(秒)Rust(debugモード)1,000,000258Rust10,000,000,00011Rust100,000,000,000(1分を超えたため中断)Python10003.8Python10000(1分を超えたため中断)Python + numba10000.2Python + numba1,000,00012.2Python + numba10,000,000(1分を超えたため中断)Python + numba(prange)1,000,0005.6Python + numba(prange)10,000,000(1分を超えたため中断)

感想

Rustの速さを実感したいのが主だったため、そもそもPythonに不利な処理を実装している点ご理解いただきたいです。(Python大好き!)
とはいえ、想像以上に速すぎて少し笑ってしまいました。
ちなみに、Rustでのf(10_000_000_000)の結果は166666666616666666670000000000でした。

广告
将在 10 秒后关闭
bannerAds