2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[Rust] 3種のべき乗演算のベンチマーク

Posted at

Rustの3種のべき乗演算の速度差について という記事の内容が驚き (powi より powf のが速い) だったので, 手元の環境でもベンチマークしてみました (環境については後述).

問題設定

元記事では $(-1)^n$ を計算していますが, 元記事で言及されている通りこれは普通 if 文を使って書くはずなので, 元記事の問題設定はあまり現実的ではないと思います. と言って Taylor 展開や多項式の計算などもべき乗を使わずに書くはずです.

そこでここでは次の和を計算するという問題を考えます.
$$S( x: T ) = \sum_{n = 0}^{127} n^x$$
ここに $T$ は変数 $x$ の型で, .pow() を用いるときは u32, .powi() を用いるときは i32, .powf() を用いるときは f64 です.

コード

長くなったので こちら に置いておきます (CC0).

なぜか bench_npow1 のみ最適化されてしまって計算時間が 0 になったので結果を標準出力することでそれを阻止しています. また最後の overhead というベンチマークは, イテレータの要素を f64 にキャストしていること, また浮動小数点数の和と整数の和を比較していること, によるオーバーヘッドの大きさを見るためのものです.

おまけとして, .powf(0.5).sqrt() の比較, べき乗をハードコードしたものも入っています.

結果

Debian 10.0 (WSL) on Win10 1903 (x86_64), Intel Core i7-6700 @3.40GHz で実行した結果です.
rustc 1.38.0-nightly (534b42394 2019-08-09)

running 11 tests
test bench_npow1    ... bench:          93 ns/iter (+/- 10)
test bench_npow2    ... bench:         159 ns/iter (+/- 23)
test bench_npow4    ... bench:         277 ns/iter (+/- 38)
test bench_npowf0_5 ... bench:       5,636 ns/iter (+/- 525)
test bench_npowf1   ... bench:         623 ns/iter (+/- 114)
test bench_npowf2   ... bench:         693 ns/iter (+/- 106)
test bench_npowf4   ... bench:       5,722 ns/iter (+/- 211)
test bench_npowi1   ... bench:         304 ns/iter (+/- 6)
test bench_npowi2   ... bench:         345 ns/iter (+/- 7)
test bench_npowi4   ... bench:         444 ns/iter (+/- 10)
test bench_nsqrt    ... bench:         210 ns/iter (+/- 10)
test bench_ntimes2  ... bench:         111 ns/iter (+/- 5)
test bench_ntimes4  ... bench:         125 ns/iter (+/- 4)
test overhead       ... bench:          98 ns/iter (+/- 4)

test result: ok. 0 passed; 0 failed; 0 ignored; 11 measured; 0 filtered out

time.png

※縦軸が対数スケールになっています.

Win10 native の環境 (nightly-x86_64-pc-windows-msvc) でも試してみましたが, powf を除いてほぼ同じ数字でした. powf については

test bench_npowf0_5 ... bench:       3,976 ns/iter (+/- 387)
test bench_npowf1   ... bench:         438 ns/iter (+/- 19)
test bench_npowf2   ... bench:       3,984 ns/iter (+/- 427)
test bench_npowf4   ... bench:       3,980 ns/iter (+/- 388)

となっていて, .powf(4.) はネイティブの方が速いのに対して, .powf(2.).powf(4.) と同程度まで遅くなっています.

なお別のPC: Debian 9.9 (native), Intel Core i7-4790K CPU @4.00GHz でも実行しましたが, WSL での結果と定性的にはほぼ同じでした.

所感

pow が一番速くて powf が一番遅いという予想通りの結果になりました. 128回のべき乗を計算しているので, 1回のべき乗には最悪で 44 ns 程度かかっている見積もりですね.

いくつか試したんですが, 底が -1 のときに powf が異様に速いという元記事の結果を再現できませんでした. 元記事のベンチマークを試してみても

test benches::bench_leibniz_f64powf ... bench:  38,408,980 ns/iter (+/- 1,565,358)
test benches::bench_leibniz_f64powi ... bench:  33,490,600 ns/iter (+/- 917,164)
test benches::bench_leibniz_i64pow  ... bench:  13,489,260 ns/iter (+/- 619,968)

で, powf が一番遅かったですし.

平方根 .sqrt() が圧倒的に速いのはともかく, べき乗をハードコードした bench_ntimes2, bench_ntimes4 が思ったよりだいぶ速かった (というか powi が遅かった) のが驚きです. もしかしたらハードコードした方は意図していない形まで最適化されていたのでしょうか?

2
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
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?