为什么在跨越CPU时块I / O完成需要这么长时间?

时间:2009-12-10 21:29:40

标签: linux-kernel linux-device-driver smp

我正试图从高端存储设备的Linux块驱动程序中挤出最高性能。目前令我有点困惑的一个问题是:如果用户任务在一个CPU上启动I / O操作(读或写),并且设备中断发生在另一个CPU上,我会产生大约80微秒的延迟任务恢复执行。

我可以使用O_DIRECT对原始块设备看到这一点,因此这不是页面缓存或与文件系统相关的。驱动程序使用make_request来接收操作,因此它没有请求队列,也没有使用任何内核I / O调度程序(你必须相信我,这种方式更快)。

我可以向自己证明,在一个CPU上调用bio_endio和在另一个CPU上重新调度的任务之间会出现问题。如果任务在同一个CPU上,它会很快启动,如果任务在另一个物理CPU上,则需要更长的时间 - 通常在我当前的测试系统上大约80微秒(英特尔5520 [NUMA]芯片组上的x86_64) )。

通过将进程和IRQ cpu亲和性设置为相同的物理CPU,我可以立即将性能提高一倍,但这不是一个好的长期解决方案 - 无论I /哪里,我都希望能够获得良好的性能。 Os起源于此。而且我只有一个IRQ,因此我一次只能将它引导到一个CPU - 如果许多线程在许多CPU上运行,那就不好了。

我可以在Centos 5.4的2.6.18到主线2.6.32的内核上看到这个问题。

所以问题是:如果我从另一个CPU调用bio_endio,为什么恢复用户进程需要更长的时间?这是调度程序问题吗?有没有办法消除或降低延迟?

4 个答案:

答案 0 :(得分:1)

如果您在特定CPU上完成I / O,则该处理器可以立即开始处理新线程 - 如果您在与所请求的线程相同的处理器上完成i / o,那么下一个线程可能是你完成i / o的那个。

另一方面,如果你在另一个处理器上完成,请求i / o的线程将无法立即运行 - 它必须等到当前正在执行的任何内容完成其量程或以其他方式放弃CPU。 / p>

据我了解。

答案 1 :(得分:1)

这可能只是从完成生物的CPU向执行任务的CPU发出IPI所固有的延迟 - 为了测试这一点,尝试使用idle=poll启动。

答案 2 :(得分:1)

This patch刚刚发布到LKML,在块设备层实现QUEUE_FLAG_SAME_CPU,其描述如下:

  

添加标志以完成请求   提交请求的cpu。该   flag暗示QUEUE_FLAG_SAME_COMP。通过   默认情况下,它已关闭。

听起来它可能正是你所需要的......

答案 3 :(得分:0)

看起来我误解了这个问题:它似乎与缓存未命中有关;当cpu处理中断不是启动i / o的cpu时,cpu可以达到100%的利用率,然后一切都变慢,给人的印象是cpu之间有很长的延迟通信。

感谢大家的想法。