デバッグビルドの速度差(C vs C++)


VisualStudioを使用していて、デバッグビルドとリリースビルドでの速度差が顕著なのは最適化の有無の点からも言うまでも無いですが、同じようなコードをC vs C++で書いたときにも何か差があるように感じてならないです。

どうしてこのような差が出てくるか調べてみたところ、1つはテンプレートの展開に関する部分が大きいのではないか、と感じました。
たとえば、STLはテンプレートの塊ですが、これを使用するとDebug/Releaseで速度差が大きいですし、よくDebugでは使用にも耐えない、と聞きます。

templateの展開はインラインに行われるため早い、とは聞きますが、インライン展開するかどうかはコンパイラが決めることなので、デバッグビルド時には展開されないことが多いです。__forceinline を付けてもデバッグビルドではアセンブリを見ると展開されていなかったりします。
デバッグしていてステップインをテンプレートの関数やメンバにしたときにも潜れるということは、展開されておらず単なる関数呼び出しになっている証拠です。同じような処理だからとローカルに書いてあったコードをテンプレートによる関数実装に切り替えた途端に速度の低下が起こると思われます。
実際に手元で型変換のためのテンプレートをCスタイルのキャストを使うように変更しただけで速度は向上しました…。あまり良くはないのですが、実装をテンプレートからマクロへ変更することも有効のように思います。

(手元の環境では20万回ほどの実行される箇所で、Cスタイルにしたことで70msほど速度向上しました。)

最後に、STLのデバッグで速度を求めるときには、_SECURE_SCL と _HAS_ITERATOR_DEBUGGING を設定してビルドするという手もあります。これらはテンプレートの展開有無ではなく、範囲チェックやイテレータの所有権チェック、同期オブジェクト使用してのアクセスチェックとかの有効/無効を切り替える仕組みとなっています。
これの注意点としては、使用するプログラム全体でこの定義を揃えたビルドを行う必要があります。間違えるとビルド失敗や妙なエラーに悩まされるんじゃないでしょうか。

※ 完全に無効化は困るので速度に関してだけちょっと恩恵を受けたい、という場合には _SECURE_SCL は1にしておくのが良さそうです。速度ペナルティは、_HAS_ITERATOR_DEBUGGING のほうが影響しているとのこと。

スポンサーリンク

シェアする

  • このエントリーをはてなブックマークに追加

フォローする