我有两个程序通过 linux 管道(命名或其他方式)相互传递数据。我需要在两个程序之间达到 ~2600 MB/s 的传输速率,但目前看到的传输速率较慢,约为 ~2200 MB/s。但是,我发现如果我将第二个进程替换为“dd”,传输速率会跃升至超过 3000 MB/s。我的程序从管道读取的方式是否比“dd”的方式效率低?我可以做些什么来提高这个吞吐量? “ifstream”本质上比其他从管道读取二进制数据的方法慢吗?
总结这两种情况:
Scenario 1:
Program 1 -> [named pipe] -> Program 2
Yields ~2200 MB/s transfer rate
Scenario2:
Program 1 -> [named pipe] -> 'dd if=pipename of=/dev/null bs=8M'
Yields ~3000 MB/s transfer rate.
这是我的程序 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(),但没有帮助。
最佳答案
差异似乎是由于使用数组而不是 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);
}
}
程序 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 基本上是数组的包装器)。
编辑:我刚刚测试了下面的程序 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 内存而不是堆栈上的内存,性能下降以匹配 vector 性能。感谢 ipc,让我了解这一点。
关于c++ - 为什么 'dd' 从管道读取的速度比我自己使用 ifstream 的程序更快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15666460/