【发布时间】:2015-07-27 17:55:28
【问题描述】:
在具有许多 CPUS 脚本的大型 SMP 机器上运行数十个同时作业(少于 CPU 数量),如下所示:
some_program -in FIFO1 >OUTPUT1 2>s_p1.log </dev/null &
some_program -in FIFO2 >OUTPUT2 2>s_p2.log </dev/null &
...
some_program -in FIFO40 >OUTPUT40 2>s_p40.log </dev/null &
splitter_program -in real_input.dat -out FIFO1,FIFO2...FIFO40
分离器读取输入数据并按顺序将其分配到 FIFO。 (记录 1,41,81... 到 FIFO1;2,42,82 到 FIFO2 等)拆分器的开销很低,并且几乎可以以文件系统提供的速度处理数据。
每个 some_program 处理其流并将其写入其输出文件。但是,没有任何东西可以控制文件系统看到这些写入的顺序。写入也非常小,大约 10 个字节。脚本“知道”这里有 40 个流,它们可以缓冲在 20M(或其他)块中,然后将每个块按顺序写入文件系统。也就是说,应该使用排队写入来最大化磁盘的写入速度。然而,操作系统只会在 40 个流中的每一个上以大致相同的速率看到一堆写入。
在实际运行过程中发生的情况是子进程获得大量 CPU 时间(在顶部,>80%),然后出现刷新进程(10% CPU),所有其他进程下降到低 CPU(1 %),然后它又回到更高的比率。这些停顿一次持续几秒钟。刷新意味着写入压倒了文件缓存。此外,我认为操作系统和/或底层 RAID 控制器可能会不规律地弹跳物理磁盘磁头,这会降低物理磁盘的最终写入速度。这只是一个猜测,因为很难说到底发生了什么,因为在写入和磁盘之间存在文件缓存(在具有超过 500Gb RAM 的系统中)和 RAID 控制器。
是否有控制这种 IO 的程序或方法,强制文件系统写入很好地排队以最大限度地提高写入速度?
“缓冲区”程序在这里没有多大帮助,因为虽然它会将输出流累积成一个大块,但不会有写入的有序排队,所以几个可能同时出去.如果输出流中的数据速率不相关,这将不是问题,但在某些情况下,所有流中的数据速率完全相同,这意味着缓冲区将同时填充。这将停止整个树,直到最后一个被写入,因为任何无法写入输出的进程都不会读取其下一个输入,这将停止拆分器,因为所有 I/O 都是同步的。缓冲区需要以循环方式清空,最好在其中任何一个完全填满之前清空,尽管当数据输出速率超过文件系统写入速率时,这可能无法避免。
有许多用于调整文件系统的参数,其中一些可能会有所帮助。调度程序已从 cfq 更改为截止日期,因为系统一次锁定了几分钟。
【问题讨论】:
-
如果你的工作是受 IO 限制的,在更多的内核上并行只会让事情变得更糟。特别是在写入 HDD 时。您是否尝试过只运行更少的作业?
-
也许你想要的是将那些 10 字节的写入累积到内存页面或磁盘块大小的块(甚至更大)中,然后异步将它们刷新到磁盘,即继续积累新的块,即使在等待旧块被提交到磁盘时也是如此。