なぜ、coutのほうが遅いのか?
どうやら double型が特に遅いみたいである。 で、かくかくしかじか辿っていった結果。 一因がnum_putクラスが遅いことが分かった。 num_putのdo_putオーバーライド
localeにnum_putを追加
●実行方法1~3で計測してみることにした。 実行方法1
実行方法2
実行方法3
結果(ms)
情報整理 ・num_putが遅いことには間違いない。 ・coutは doubleを置換する場合、try catchを行っている。 ・coutのostream の出力方法は4×nバイト または1バイトのみである。 ・coutのostreambufの出力方法はnバイト または1バイトのみである。 ・coutのnum_putの出力対象はchar型のiter_typeなので出力方法は1バイトのみである。 ・coutはostreambufでバッファを抽象化し、osteramで循環キューを抽象化している。 結論 coutまわりはクラスが立て込んでいて、ostreambufにフォーマッタがあればいいが フォーマッタはostreamはlocaleに散らばっている。 これらはostreamが使うワーク領域がostearmbufが管理するワーク領域が 異なっていることに起因しているのかもしれない。 ただし、num_putの中身がどうなっているのか未確認のため怪しい。 また、printf系はバッファを素直にI/Oにしているため FILEポインタのみを通しているのに対し、writerと媒体の距離が近いのに対し cout系はostreamからnum_putを経てostreambufの間を1バイトずつ細切れで渡していってる模様。 writerとバッファの距離は遠そうなイメージ? そんなこんなで、よっぽど最適化されるようにならないと 関数を読んでるだけのprintf系に追いつくのは厳しいと思われる。 きっとjavaの初期のころってこういう課題をなんとかインラインになるように 頑張ったんだろうなと。 しかし、C++の場合はジェネリックはテンプレート頼みだし coutなんて標準ライブラリだからインラインにする前に コンパイル済みの関数に紐づくんじゃないかなぁと。 PR |
|
忍者ブログ [PR] |