スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

C++ のoperator>>によるキャストはとんでもなく遅い

いままであまりIOのパフォーマンスが大きな問題になる、という事態に直面してこなかったのですが、
最近になってC++のstreamの>>演算子の速度が非常に遅いということに気づきました。

C++の場合、

float f;
cin >> f;

のような形で実数に限らずあらゆるデータをキャストしてファイルなどから読み込めるわけですが、
これは便利ではあるのですが、速度が非常に遅いようで、たとえば

string s;
cin >> s;
float f = atof(c.c_str());

等のように、atofに書き換えるだけでも相当な高速化になるようです。

そこで、今回はC++で簡単に使える実数のキャストの性能比較を行ってみました。


・検証コード
#include "stdafx.h"

#include <Windows.h>

#include <iostream>
#include <sstream>
#include <string>
using namespace std;


// テストデータ作成.
// 同じ値の実数がスペース区切りで大量に並んだ文字列を作る
void create_src(string& src)
{
    ostringstream out;
    forint i = 0; i < 400000; ++i)
    {
        out << "12.345" << " ";
    }
    out << endl;

    src = out.str();
}


// stream内の数の総和を求める. operator>> 式
float getsum_a(istringstream& in)
{
    float sum = 0;
    while(!in.eof())
    {
        float f = 0;
        in >> f;
        sum += f;
    }

    return sum;
}

// stream内の数の総和を求める. stof式
float getsum_b(istringstream& in)
{
    float sum = 0;
    while(!in.eof())
    {
        string s;
        in >> s;
        if (s.empty())
            continue;

        sum += std::stof(s.c_str());
    }

    return sum;
}

// stream内の数の総和を求める. atof式
float getsum_c(istringstream& in)
{
    float sum = 0;
    while(!in.eof())
    {
        string s;
        in >> s;
        if (s.empty())
            continue;

        sum += ::atof(s.c_str());
    }

    return sum;
}


// 関数の速度調査機能.
void plot_func_speed(string src, float (func)(istringstream&))
{
    istringstream a(src);

    DWORD t0 = GetTickCount();

    float sum = func(a);

    DWORD t1 = GetTickCount();

    cout << sum << " " << (t1 - t0) << endl;
}


int _tmain(int argc, _TCHAR* argv[])
{
    string src;
    create_src(src);

    plot_func_speed(src, getsum_a);
    plot_func_speed(src, getsum_b);
    plot_func_speed(src, getsum_c);

    getchar();

    return 0;
}


上記のコードでは、文字列で大量の実数が入っているストリームから、数値をピックアップする処理が、
キャストの種類によってどの程度性能差があるかを比較しています。

それぞれ、

getsum_a : operator>>演算子によるキャスト
getsum_b : streamから一旦stringで文字列を受け取り、std::stofでキャスト
getsum_c : streamから一旦stringで文字列を受け取り、atofでキャスト

となっております。

で、それぞれの速度を私のPCで実行させたところ、処理にかかった時間は下記のようになりました。

getsum_a : 3463ms
getsum_b : 234ms
getsum_c : 216ms

operator>>を基準とした速度比は、

getsum_a : 1
getsum_b : 14.8
getsum_c : 16.0

と、atofを使った場合はoperator>>よりも16倍も高速になりました。


ということで、operator>>は任意の型変換処理を統一された記述で表現できたり、そもそもコード量が少ない、
といったメリットがありますが、入力が明らかに数であることがわかっているような場合は、
一旦string化してからstd::stof等を使ったほうがよさそうです。
スポンサーサイト

コメントの投稿

非公開コメント

カレンダー
10 | 2017/11 | 12
- - - 1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 - -
最新記事
カテゴリ
Qt (21)
SDL (2)
MFC (2)
検索フォーム
月別アーカイブ
最新コメント
最新トラックバック
RSSリンクの表示
リンク
リンク(管理用)
FC2カウンター
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。