ある一定数で折り返して用いたいような数があった場合、ぱっと思いつくのは、if文を用いて初期化するやり方と、%で剰余を取る方法でしょうか。
例えば以下のようなコードです。
//if文を用いたコード while(i < MAX) { if((j+=1) == 100) j = 0; i++; } //%を用いたコード while(i < MAX){ j = (j+1)%100; i++; }
どちらのコードでも、jが100になったら0に戻す、という処理をしています。
このif文を用いて初期化する方法と、%で剰余を取るコード、どちらが高速なのか気になったので、検証を行ってみました。
実行環境
実行環境は以下の通りです。
OS | Windows10 Pro |
---|---|
CPU | Core i7 6700 |
MEM | DDR4 2133CL13 8GBx2 |
コンパイラ(コンパイルオプション) | g++5.3.0-3(-Wall -O3) |
実行したコード
プロジェクト全体はGitHubに上げました。
github.com
#include <iostream> #include <chrono> using namespace std; constexpr int MAX = 1000000000; int If(){ int i = 0; int j = 0; chrono::system_clock::time_point start, end; start = chrono::system_clock::now(); while(i < MAX) { if((j+=1) == 100) j = 0; i++; } end = chrono::system_clock::now(); cout << "if time\t\t:" << chrono::duration_cast<chrono::milliseconds>(end-start).count() <<endl; return i + j; } int Mod(){ int i = 0; int j = 0; chrono::system_clock::time_point start, end; start = chrono::system_clock::now(); while(i < MAX){ j = (j+1)%100; i++; } end = chrono::system_clock::now(); cout << "mod time\t:" << chrono::duration_cast<chrono::milliseconds>(end-start).count() <<endl; return i + j; } int main() { int Ifres, Modres; Ifres = If(); Modres = Mod(); cout << "if result\t:" << Ifres << '\n' << "mod result\t:" << Modres << endl; return 0; }
実行結果
実行結果は以下の通りです。
10回ほど実行して最速だったものを選びました。
Mod | If |
---|---|
3088[ms] | 1403[ms] |
結論
検証はガバガバですが、一目でわかる通りif文方が倍以上高速ですね。
大体の平均では実行時間は半分程度でしたが、iの加算処理が等しく入っていることを考えると、倍以上速いという結論は揺らがないでしょう。
あまり差が出なかったらちゃんと検証するためのコードを書くつもりでしたが、その必要も無かったです。
実験前は、加算と保存の後で更に処理を行うということで、if文を用いた処理の方が遅いのかなと思っていましたが、最適化レベルなどを弄ってみても、やはりif文を用いた方が速かったです。
恐らくif文の方が%演算子よりも分岐予測がしっかりしているためなのでしょうね。
おまけ
javaでもやってみました。
wrongwrong163377.hatenablog.com
参考にしたサイト
時間計測はこちらのサイトを参考にさせて頂きました。
qiita.com