8

Linuxパイプ(名前付きまたはその他)を介して互いにデータを渡す2つのプログラムがあります。2 つのプログラム間で ~2600 MB/s の転送速度を達成する必要がありますが、現在、約 ~2200 MB/s の遅い速度が見られます。ただし、2 番目のプロセスを代わりに「dd」に置き換えると、転送速度が 3000 MB/s を超えることがわかりました。私のプログラムがパイプから読み取る方法について、「dd」の方法よりも効率が悪いものはありますか? このスループットを改善するにはどうすればよいですか? 「ifstream」は、パイプからバイナリデータを読み取る他の方法よりも本質的に遅いですか?

2 つのシナリオを要約すると、次のようになります。

シナリオ 1:

プログラム 1 -> [名前付きパイプ] -> プログラム 2

~2200 MB/秒の転送速度を実現

シナリオ 2:

プログラム 1 -> [名前付きパイプ] -> 'dd if=pipename of=/dev/null bs=8M'

~3000 MB/秒の転送 速度が得られます。

私のプログラム2が現在パイプから読み取る方法は次のとおりです。

ifstream inputFile;
inputFile.open(inputFileName.c_str(), ios::in | ios::binary);
while (keepLooping)
{
    inputFile.read(&buffer[0], 8*1024*1024);
    bytesRead = inputFile.gcount();
    //Do something with data
}

アップデート:

istream の代わりに 'read(fd, &buffer[0], 8*1024*1024)' を使用してみましたが、軽度の改善が見られました (ただし、dd ほどではありません)

また、stream->read() の代わりに stream->rdbuf()->sgetn(&buffer[0], 8*1024*1024) を使用してみましたが、役に立ちませんでした。

4

2 に答える 2

3

違いは、std::vector の代わりに配列を使用しているためと思われますが、これはまだ信じられません。比較のために、私の 2 つのコード セットを以下に示します。1 つ目は、プログラム 1 から約 2500 MB/秒の速度で取り込むことができます。2 番目は、3100 MB/秒の速度で取り込むことができます。

プログラム 1 (2500 MB/秒)

int main(int argc, char **argv)
{
    int fd = open("/tmp/fifo2", O_RDONLY);

    std::vector<char> buf(8*1024*1024);

    while(1)
    {
       read(fd, &buf[0], 8*1024*1024);
    }
}

プログラム 2 (3100 MB/秒)

int main(int argc, char **argv)
{

    int fd = open("/tmp/fifo2", O_RDONLY);

    char buf[8*1024*1024];

    while(1)
    {
       read(fd, &buf[0], 8*1024*1024);
    }
}

両方とも、gcc バージョン 4.4.6 を使用して -O3 でコンパイルされます。誰かがこの理由を説明できれば、私は非常に興味があります (std::vector は基本的に配列のラッパーであると理解しているため)。

編集: ifstream を使用でき、3000 MB/s で実行できる以下のプログラム 3 をテストしました。そのため、'read()' の代わりに ifstream を使用すると、パフォーマンスがわずかに低下するようです。std::vector を使用した場合のヒットよりもはるかに少ない。

プログラム 3 (3000 MB/s)

int main(int argc, char **argv)
{
    ifstream file("/tmp/fifo2", ios::in | ios::binary);

    char buf[8*1024*1024];

    while(1)
    {
       file.read(&buf[0], 32*1024);
    }
}

編集2:

スタック上のメモリの代わりに malloc されたメモリを使用するようにプログラム 2 のコードを変更したところ、ベクトルのパフォーマンスと一致するようにパフォーマンスが低下しました。ありがとう、ipc、私にこれを教えてくれて。

于 2013-03-27T20:09:02.213 に答える
1

でコンパイルされたこのコードg++ -Ofast:

int main(int argc, char *argv[])
{
  if (argc != 2) return -1;
  std::ifstream in(argv[1]);
  std::vector<char> buf(8*1024*1024);
  in.rdbuf()->pubsetbuf(&buf[0], buf.size());
  std::ios_base::sync_with_stdio(false);
  std::cout << in.rdbuf();
}

それほど悪いパフォーマンスはまったくありません。

$ time <<this program>> <<big input file>> >/dev/null
0.20s user 3.50s system 9% cpu 40.548 total
$ time dd if=<<big input file>> bs=8M > /dev/null
0.01s user 3.84s system 9% cpu 40.786 total

オフにしないと本当に時間がかかるstd::coutバッファを共有することを考慮する必要があります。stdoutしたがってstd::ios_base::sync_with_stdio(false);、速度が必要で、C の入出力メソッド (どちらにしても遅い) を使用するつもりがない場合は、呼び出します。

また、C++ で生で高速な入出力を行うにはstreambuf、 によって取得されるからのメソッドを使用しますrdbuf()

于 2013-03-27T18:53:48.033 に答える