我有两个程序通过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
}
更新
我现在尝试使用'read(fd,& buffer [0],8 * 1024 * 1024)'代替istream,似乎显示温和的改进(但不如DD)
我也尝试过使用stream-> rdbuf() - > sgetn(& buffer [0],8 * 1024 * 1024)而不是stream-> read(),这没什么用。
答案 0 :(得分:3)
差异似乎是由于使用数组而不是std :: vector,我仍然很难相信。我的两组代码如下所示,以供比较。第一个可以以大约2500 MB / s的速率从程序1中摄取。第二种可以以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,让我知道这个。
答案 1 :(得分: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
共享一个缓冲区,如果不关闭它真的非常耗时。所以如果你想要速度而不打算使用C的输入输出方法(无论如何都要慢),请调用std::ios_base::sync_with_stdio(false);
。
此外,对于C ++中的原始和快速输入/输出,请使用streambuf
获得的rdbuf()
中的方法。