iostream vs stdio

結論としてiostream vs stdioではなく、ofstream vs fprintfの比較になってますもう過去に幾度と無くされてきた戦争な気がするのでドキュメントとして残す。

iostreamはデフォルトでstdioより遅い。
ただし、http://homepage1.nifty.com/herumi/diary/0812.html#25 のように
tie(0) + sync_with_stdio(false)を読んでおけば改善される(はず)

といってもベンチマークをとらないと何ともいえないので検証。

ってことでまずは検証ソース(ツッコミ歓迎、ちなみに560Mほどのファイルが出るので注意)

#include<cstdio>
#include<vector>
#include<iostream>
#include<fstream>
#include<boost/timer.hpp>

const int loop_max = 5;
const int NX=256,NY=256,NZ=256;
const int DX=1./NX,DY=1./NY,DZ=1./NZ;

void iotest_stdio(const std::vector<double>& data) {
	FILE* fp=fopen("data.dat","w");
	for(int c=0;c<loop_max;++c) {
		for(int i=0;i<NX;++i) {
			for(int j=0;j<NY;++j) {
				for(int k=0;k<NZ;++k) {
					const double x=i*DX,y=j*DY,z=k*DZ;
					fprintf(fp,"%f %f %f\n",x,y,z,data[i*NX*NY+j*NY+k]);
				}
			}
		}
	}
	fclose(fp);
}
void iotest_stream(const std::vector<double>& data) {
	std::ofstream ofs("data.dat");
	for(int c=0;c<loop_max;++c) {
		for(int i=0;i<NX;++i) {
			for(int j=0;j<NY;++j) {
				for(int k=0;k<NZ;++k) {
					const double x=i*DX,y=j*DY,z=k*DZ;
					ofs << x << " " << y << " " << z << " "
						<< data[i*NX*NY+j*NY+k];
				}
			}
		}
	}
}

int main() {
	std::vector<double> data(NX*NY*NZ);
	{
		std::cout << "iotest stdio : ";
		boost::timer timer;
		iotest_stdio(data);
		const double elapsed = timer.elapsed();
		std::cout << elapsed << std::endl;
	}
	{
		std::cout << "iotest stream without tie(0)+sync_with_stdio(false) : ";
		boost::timer timer;
		iotest_stream(data);
		const double elapsed = timer.elapsed();
		std::cout << elapsed << std::endl;
	}
	{
		std::cout << "iotest stream with tie(0)+sync_with_stdio(false) : ";
		std::cin.tie(0);
		std::ios::sync_with_stdio(false);
		boost::timer timer;
		iotest_stream(data);
		const double elapsed = timer.elapsed();
		std::cout << elapsed << std::endl;
	}
	return 0;
}

結果(環境はLinux,g++ (GCC) 4.4.5 20101112 (Red Hat 4.4.5-2), -O3最適化)
iotest stdio : 51.38
iotest stream without tie(0)+sync_with_stdio(false) : 114.49
iotest stream with tie(0)+sync_with_stdio(false) : 114.55


tie(0) + sync_with_stdio(false)で改善されなかった!あれ?

追記:

らしいので再度検証

あと

というコメントのように今回はofstreamしか使ってないのでcin.tie(0)は関係ないはずです。あってもなくても変わらないはずなので消さずに入れてます。無駄・・

再検証結果
sync_with_stdio(false)をつけた場合のmain関数を次のように変えてます。
他は上記ソースと同じ

int main() {
    std::cin.tie(0);
    std::ios::sync_with_stdio(false);
    std::vector<double> data(NX*NY*NZ);
    {
        std::cout << "iotest stream with tie(0)+sync_with_stdio(false) : ";
        boost::timer timer;
        iotest_stream(data);
        const double elapsed = timer.elapsed();
        std::cout << elapsed << std::endl;
    }
    return 0;
}

iotest stdio : 51.15
iotest stream without tie(0)+sync_with_stdio(false) : 114.12
iotest stream with tie(0)+sync_with_stdio(false) : 113.29

誤差の範囲でしか変わらないですね。ツッコミまだまだ歓迎です
ちなみにtieとsync_with_stdioの呼び出し順を逆にしても同じ。

さらに追記:

真偽や詳細なところはまだ不明ですが、たしかにcinはもちろんsync_with_stdioだって"stdio"って言ってるし、fstreamでは関係ないかも。
ということで今回の検証は単純にfprintfとofstreamの比較ということで終わり?
stdioでの比較してませんけど、私の場合、数GB単位のデータ出力となるのでファイルへのIO以外は意味が無い。ってことで他の人にパス。