stdoutにバイト数を送信するためにC / C ++の最良の方法
-
22-08-2019 - |
質問
私のプログラムをプロファイリングし、機能の印刷は実行するために多くの時間を取っています。どのように私は(stdoutに同時に(印刷中のすべての9bytesを送信する必要がある))の代わりにfwriteのを使用して、より速くそれを作るのstdoutに直接「生の」バイト出力を送ることができますか?
void print(){
unsigned char temp[9];
temp[0] = matrix[0][0];
temp[1] = matrix[0][1];
temp[2] = matrix[0][2];
temp[3] = matrix[1][0];
temp[4] = matrix[1][1];
temp[5] = matrix[1][2];
temp[6] = matrix[2][0];
temp[7] = matrix[2][1];
temp[8] = matrix[2][2];
fwrite(temp,1,9,stdout);
}
マトリックスはunsigned char型行列であることがグローバルに定義されている[3] [3];
解決
IOは安価な操作ではありません。それはあなたがより多くのCPUバウンドのプロセスが実行できるようにwrite
を呼び出すときに完了するために書いているIOデバイスの前にOSは、あなたのプロセスを先取りできることを意味し、事実、のブロックの操作では、操作。
(あなたは* nixのマシン上で開発している場合)に使用できる唯一の低レベルの機能は、生write
機能を使用することですが、でも、あなたのパフォーマンスがそれほど速く、それは今よりもされません。簡単に言えば:IOは高価です。
他のヒント
トップクラスの答えは、IOが遅いことを主張しています。
ここで重要な性能パスのうち、OSを取るために十分な大きさのバッファを持つ迅速なベンチマークだが、唯一のの場合のあなたは巨大なblurpsであなたの出力を受け取るために喜んでいます。最初のバイトまでの待ち時間が問題である場合は、「dribs」モードで実行する必要があります。
9つのバイト配列から10万件のレコードを書く
GCC 4.6.1の下で3GHzのCoreDuoのミント12 AMD64
340ms to /dev/null
710ms to 90MB output file
15254ms to 90MB output file in "dribs" mode
打ち鳴らす3.0の下で2.4GHzのCoreDuoのFreeBSDの9 AMD64
450ms to /dev/null
550ms to 90MB output file on ZFS triple mirror
1150ms to 90MB output file on FFS system drive
22154ms to 90MB output file in "dribs" mode
あなたが適切にバッファリングする余裕がある場合は、IOについての遅いものは何もありません。
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char* argv[])
{
int dribs = argc > 1 && 0==strcmp (argv[1], "dribs");
int err;
int i;
enum { BigBuf = 4*1024*1024 };
char* outbuf = malloc (BigBuf);
assert (outbuf != NULL);
err = setvbuf (stdout, outbuf, _IOFBF, BigBuf); // full line buffering
assert (err == 0);
enum { ArraySize = 9 };
char temp[ArraySize];
enum { Count = 10*1000*1000 };
for (i = 0; i < Count; ++i) {
fwrite (temp, 1, ArraySize, stdout);
if (dribs) fflush (stdout);
}
fflush (stdout); // seems to be needed after setting own buffer
fclose (stdout);
if (outbuf) { free (outbuf); outbuf = NULL; }
}
あなたが行うことができ、出力のrawest形式は、次のように
、予想write
システムコールであります
write (1, matrix, 9);
1(0で標準であり、2は標準誤差である)を、標準のファイル記述子です。あなたの標準出力にのみもう一方の端にそれを読ん1(すなわち、端末、またはあなたにpipeingしているプログラム)かなり遅いかもしれないほど高速で書き込みます。
私は100%わからないんだけど、あなたは(fcntl
を使用して)、FD 1上の非ブロッキングIOを設定してみてください、それはもう一方の端によって消費されるまでOSはあなたのためにそれをバッファリングを願っています可能性があります。これは、しばらくしているが、私はそれがこのようにうまくいくと思う。
fcntl (1, F_SETFL, O_NONBLOCK);
しかしYMMV。私は構文上間違っている場合、私が言ったように、それはしばらくしている、私を修正してください。
おそらく、あなたの問題はそのfwriteのではありません()が遅いですが、それはバッファリングされています。 )(fwriteの後にfflush(標準出力)を呼び出してみます。
これは、すべて本当にこの文脈では遅いのあなたの定義に依存します。
すべての印刷は、かなり遅いです。
あなたの最善の策は、の線に沿って何かをprintf関数を使用することです
printf("%c%c%c%c%c%c%c%c%c\n", matrix[0][0], matrix[0][1], matrix[0][2], matrix[1][0],
matrix[1][1], matrix[1][2], matrix[2][0], matrix[2][1], matrix[2][2]);
あなたは単にすることができます:
std::cout << temp;
のprintfののより多くのC-スタイルです。
しかし、IO操作が高価であるので、賢明にそれらを使用します。
高価です。それをデバッグするために必要なとき、私は通常、いくつかの基準に基づいて、マトリックスの条件COUTをやってしまっています。
あなたのアプリがコンソールアプリケーションである場合は、それをファイルにリダイレクトしてみてください。そして、それはコンソールの更新を行うよりもはるかに高速になります。例えばapp.exeの> matrixDump.txt
と間違って何ます:
fwrite(matrix,1,9,stdout);
1および2次元配列の両方が同じメモリを取る。
を2回プログラムを実行してみてください。出力付きとなしの一回一回。あなたは全体的に、IOないものが最速であることがわかります。また、あなたはプロセスをフォーク(またはスレッドを作成)、ファイル(stdout)に1回の書き込み、および1つは、操作を行うことができます。