为什么可以'd '从管道读取比我自己的程序使用ifstream更快
Why can 'dd' read from a pipe faster than my own program using ifstream?
我有两个程序,它们通过linux管道(命名的或其他的)相互传递数据。我需要在两个程序之间达到~2600 MB/s的传输速率,但目前看到的速率较慢,约为~2200 MB/s。然而,我发现如果我用"dd"代替我的第二个进程,传输速率会跳到3000 MB/s以上。我的程序从管道中读取数据的方式是否比"dd"的方式效率低?我可以做些什么来提高吞吐量?是否'ifstream'固有地比从管道读取二进制数据的其他方法慢?
总结两种场景:
下面是我的程序2当前从管道中读取的方式:场景1:
程序1 ->[命名管道]->程序2
传输速率~ 2200mb/s
Scenario2:
程序1 -> [named pipe] -> 'dd if=pipename of=/dev/null bs=8M'
产生~3000 MB/s的传输率。
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,这一点我仍然很难相信。下面展示了我的两组代码进行比较。第一个可以以大约2500mb/s的速率从程序1中摄取。第二个可以以3100 MB/s的速率摄取。
程序1 (2500mb/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 (3100mb/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);
}
}
都是使用-O3使用gcc版本4.4.6编译的。如果有人能解释这个原因,我会非常感兴趣(因为我理解std::vector基本上是一个数组的包装器)。
Edit:我刚刚测试了下面的程序3,它可以使用ifstream并以3000 MB/s的速度运行。因此,使用ifstream而不是'read()'似乎会导致非常轻微的性能下降。远小于使用std::vector.
程序3 (3000mb/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,让我知道这个
用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()
获得。
- 分发我自己的程序的几个问题
- C++联系人处理程序与自己的动态模板向量类
- 如何将用户代码合并到我自己的应用程序中?
- Windows:创建自己的杀死程序
- C 程序要读取包含两个双重值的Excel数据的单列,这些值由逗号分隔并存储在自己的数组中
- 预览一些自己的应用程序
- 在您自己的Qt应用程序中使用您自己的静态库
- 是否可以使程序的执行跳过 fprintf-语句/如何创建我自己的 fprintf 函数
- 从自己的程序获取程序元数据
- 我们如何让C++程序自己修复超出范围的数组索引
- 在C程序中创建我自己的std::vector
- 如何将TortoiseOverlays与我自己的处理程序一起使用
- 我从哪里开始编写自己的计算器程序
- 如何使程序能够在运行时写入自己的可执行文件
- 我该如何编写一个通过从shell运行来编译自己的c++程序
- 如何将CodeSynthesis XSD包含到自己的应用程序中
- boost.log std::异常格式化程序找不到运算符<< 自己的命名空间中的重载
- 在自己的应用程序中插入具有WebRTC支持的web框架
- 为什么我们需要写一个自己的复制程序,而我们可以使用复制shell命令
- 为什么可以'd '从管道读取比我自己的程序使用ifstream更快