19

我正在尝试使用 64 位CentOS 6 将超高速数据从一个应用程序传输到另一个应用程序。我已经完成了以下基准测试dd,发现管道阻碍了我,而不是我的程序中的算法。我的目标是达到 1.5 GB/s 左右。

首先,没有管道:

dd if=/dev/zero of=/dev/null bs=8M count=1000
1000+0 records in
1000+0 records out
8388608000 bytes (8.4 GB) copied, 0.41925 s, 20.0 GB/s

接下来,两个 dd 进程之间的管道:

dd if=/dev/zero bs=8M count=1000 | dd of=/dev/null bs=8M
1000+0 records in
1000+0 records out
8388608000 bytes (8.4 GB) copied, 9.39205 s, 893 MB/s

我可以对内核或其他任何可以提高通过管道运行数据的性能的调整吗?我也尝试过命名管道,并得到了类似的结果。

4

2 回答 2

6

你试过用更小的积木吗?

当我在自己的工作站上尝试时,我注意到降低块大小时的连续改进。在我的测试中,它只在 10% 的范围内,但仍然是一个改进。您正在寻找 100%。

事实证明,进一步测试,非常小的块大小似乎可以解决问题:

我试过了

dd if=/dev/zero bs=32k count=256000 | dd of=/dev/null bs=32k
256000+0 records in
256000+0 records out
256000+0 records in
256000+0 records out
8388608000 bytes (8.4 GB) copied8388608000 bytes (8.4 GB) copied, 1.67965 s, 5.0 GB/s
, 1.68052 s, 5.0 GB/s

和你原来的

dd if=/dev/zero bs=8M count=1000 | dd of=/dev/null bs=8M
1000+0 records in
1000+0 records out
1000+0 records in
1000+0 records out
8388608000 bytes (8.4 GB) copied8388608000 bytes (8.4 GB) copied, 6.25782 s, 1.3 GB/s
, 6.25203 s, 1.3 GB/s

5.0/1.3 = 3.8 所以这是一个相当大的因素。

于 2012-09-27T19:58:49.073 回答
3

似乎 Linux 管道一次只能为读取器产生 4096 个字节,而不管写入器的写入量有多大。

因此,每次 write(2) 系统调用尝试将超过 4096 字节填充到已经填充的管道中只会导致写入器停止,直到读取器可以调用从管道中提取那么多数据并执行任何处理所需的多次读取它有心去做。

这告诉我,在多核或多线程 CPU 上(还有人制造单核、单线程、CPU 吗?),通过让管道中的每个写入器只写入 4096,可以获得更多的并行度,从而缩短经过的时钟时间一次字节,然后再回到它可以做的任何数据处理或生产,以制作下一个 4096 块。

于 2019-11-15T00:17:43.597 回答