8

我有两个程序通过 linux 管道(命名或其他方式)相互传递数据。我需要在两个程序之间达到 ~2600 MB/s 的传输速率,但目前看到的传输速率较慢,约为 ~2200 MB/s。但是,我发现如果我用 'dd' 替换我的第二个进程,传输速率会跃升至超过 3000 MB/s。我的程序从管道读取的方式是否比“dd”的方式效率低?我可以做些什么来提高这个吞吐量?'ifstream' 本质上是否比从管道读取二进制数据的其他方法慢?

总结一下这两种情况:

场景一:

程序 1 -> [命名管道] -> 程序 2

产生约 2200 MB/s 的传输速率

场景2:

程序 1 -> [命名管道] -> 'dd if=pipename of=/dev/null bs=8M'

产生约 3000 MB/s 的传输 速率。

这是我的程序 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
}

更新:

我现在尝试使用 'read(fd, &buffer[0], 8*1024*1024)' 而不是 istream,似乎有轻微的改善(但不如 dd)

我还尝试使用 stream->rdbuf()->sgetn(&buffer[0], 8*1024*1024) 而不是 stream->read(),但没有帮助。

4

2 回答 2

3

差异似乎是由于使用数组而不是 std::vector,我仍然很难相信。我的两组代码如下所示以进行比较。第一个可以从 Program 1 以大约 2500 MB/s 的速率摄取。第二个可以以 3100 MB/s 的速率摄取。

程序 1 (2500 MB/s)

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/s)

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 基本上是一个数组的包装器)。

编辑:我刚刚测试了下面的程序 3,它可以使用 ifstream 并以 3000 MB/s 的速度运行。因此,使用 ifstream 而不是 'read()' 似乎会导致非常轻微的性能下降。比使用 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:

我修改了程序 2 的代码以使用 malloc 的内存而不是堆栈上的内存,并且性能下降以匹配向量性能。谢谢,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 回答