为什么'dd'能够比使用ifstream的程序更快地读取管道?

Kyl*_*leL 8 c++ linux pipe ifstream

我有两个程序通过linux管道(命名或其他)传递数据.我需要在两个程序之间达到~2600 MB/s的传输速率,但目前看到的速度约为~2200 MB/s.但是,我发现如果用'dd'代替我的第二个进程,传输速率会跳到3000 MB/s以上.关于我的程序从管道中读取的方式是否存在一些效率低于'dd'的方式?我该怎么做才能提高吞吐量?'ifstream'本身是否比从管道中读取二进制数据的其他方法慢?

总结这两种情况:

场景1:

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

产量~2200 MB/s传输速率

Scenario2:

程序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
}
Run Code Online (Sandbox Code Playgroud)

更新:

我现在尝试使用'read(fd,&buffer [0],8*1024*1024)'代替istream,似乎显示出轻微的改善(但不如dd那么多)

我也尝试使用stream-> rdbuf() - > sgetn(&buffer [0],8*1024*1024)而不是stream-> read(),这没有用.

Kyl*_*leL 3

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

方案 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

节目 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

两者均使用 gcc 4.4.6 版本通过 -O3 进行编译。如果有人可以解释其原因,我会非常感兴趣(因为我理解 std::vector 基本上是数组的包装器)。

编辑:我刚刚测试了下面的程序 3,它可以使用 ifstream 并以 3000 MB/s 的速度运行。因此,使用 ifstream 而不是“read()”似乎会导致非常轻微的性能下降。比使用 std::vector 所造成的影响要小得多。

方案 3(3000 MB/秒)

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑2:

我修改了程序 2 的代码以使用 malloc 内存而不是堆栈上的内存,并且性能下降以匹配向量性能。谢谢 ipc,让我了解这一点。