1

それはすべてこの質問から始まりました->ファイルからデータのブロックを読み取り、そのブロックからベクターに読み取る方法は?

ディスク I/O 操作を最小限に抑える目的で、いくつかの実験を行って、バッファーのサイズがプログラムの所要時間に何らかの影響を与えるかどうかを確認しました。

次の 2 つのコードを使用しました。1 つは C 指向で、もう 1 つは C++ です (ただし、どちらも gcc でコンパイルされています)。

C 指向のコード:-

int buffer_size=1024;
FILE *file;
file = fopen(argv[1], "r");
FILE *out_file;
out_file = fopen("in", "w");
char out_buffer[2048];
setvbuf(out_file, out_buffer, _IOFBF, buffer_size);
char buffer[2048];
setvbuf(file, buffer, _IOFBF, buffer_size);
while (!feof(file)) 
{
 char sl[1000];
 fgets(sl, 140 , file);
 fputs(sl, out_file);

}

Cコードは次の結果をもたらしました(14 mbファイルの場合):-

Buffer_size      Time
10               18 sec
100              2 sec
1024             0.4 sec              
10240            0.3 sec 

(103 mb ファイルの場合)

1024             ~8 sec
5120             ~3 sec
10240            ~3 sec
15360            ~3 sec

約 5 mb のバッファー サイズで飽和点に達するようです。これには何か特別な理由がありますか?

C++ 指向のコード:-

int buffer_size=1024;
ifstream in_file(argv[1]);
char in_buffer[buffer_size];
in_file.rdbuf()->pubsetbuf(in_buffer,sizeof(in_buffer));
ofstream out_file("in");
char out_buffer[buffer_size];
out_file.rdbuf()->pubsetbuf(out_buffer,sizeof(in_buffer));
while(!in_file.eof())
{
    char sl[1024];
    in_file >> sl;
    out_file << sl<<endl;
}

私のテスト入力ファイルは、1000000 行の 14MB ファイルでした。

Buffer_size      Time (~)
10               6.5 sec
100              6.5 sec
1024             6.5 sec  

C++ はバッファ サイズをまったく気にしていないようです。なんで?

また、C++ コードは約 15 倍遅くなります (C のバッファー サイズが 1 mb の場合)。通常、ifstream は FILE よりも遅いですか (SO に関する他の回答は、違いがないことを示唆しているようです)。または、速度低下の原因となっているコードが他にあるのでしょうか?

4

3 に答える 3

2

基本的に、執筆に費やされる時間は、次の形式の式で見積もられます。

T = C1*nsyscalls + C2*nbytes

実際にC1は、 は非常に大きな定数 (syscall あたりのコスト) でC2あり、非常に小さな定数 (バイトあたりのコスト) です。バッファのサイズは比率の大きさに影響しますnsyscalls/nbytes。バッファが大きいほど小さくなります。バッファリングの目標は、第 2 項が第 1 項を支配し、 が残ることにnsyscalls比べて十分に小さくすることです。バッファーが十分に大きくなり、第 2 項が支配的になると、バッファー サイズをさらに大きくしても、パフォーマンスが大幅に向上することはありません。nbytesT = (C2+epsilon)*nbytes

于 2013-03-01T04:37:57.523 に答える
2

iostream の書式付き入力 >> はかなり遅いことが知られています。しかし、問題は、istream >> std::string または char * がスペースで区切られた単語を読み取っているため、リンゴとリンゴを比較しないことです。fgets が行うことではありません。したがって、 std::string には std::getline を、 char * には istream::getline() を使用して同様の機能を持たせると、比較がより意味のあるものになります。

PS このでは、ファイルが開かれる前に pubsetbuf() が呼び出されます。これが、ファイルを開いた後に pubsetbuf() を呼び出しても、コードの読み取り速度の変化が見られない理由である可能性があります。

于 2013-03-01T04:33:02.670 に答える
0

C++ コードの問題は、streambuf でバッファー サイズを設定する方法がないことです。を呼び出すpubsetbuf(0, 0)と、出力ファイルストリームがバッファリングされなくなりますが、他の値を使用しても特に何もしません。仕様から:

basic_streambuf* setbuf(char_type* s, streamsize n);

影響: ストリームで I/O が発生する前に setbuf(0,0) が呼び出されると、ストリームはバッファリングされなくなります。それ以外の場合、結果は実装定義です。「バッファなし」とは、pbase() と pptr() が常に null を返し、ファイルへの出力ができるだけ早く表示されることを意味します。

あなたの場合、実装は setbuf を無視するように見えます...

于 2013-03-01T07:25:15.547 に答える