硬件预取与软件预取
在计算机书中多次看到硬件预取的介绍,这块功能对上层程序是透明的,系统中也缺少观测的手段。
在研究 dpdk 时了解到软件预取相关的知识,软件预取实际是软件通过调用 prefetch 等指令来通知 cpu 预取相应的内存到 cache 中。
软件预取的实例
dpdk l2fwd 示例程序中有如下代码:
for (j = 0; j < nb_rx; j++) {
m = pkts_burst[j];
rte_prefetch0(rte_pktmbuf_mtod(m, void *));
l2fwd_simple_forward(m, portid);
}
上面的逻辑在发本次的 mbuf 报文前,提前预取 mbuf 中的报文内容到所有 cache 级别中,报文真正发送在 l2fwd_simple_forward 函数中进行。
在报文真正发送前有如下操作:
- 修改 mbuf 中的源目的 mac
- 将报文投递到 tx_buffer 中
- 当 tx_buffer 的发包门限值到达后,调用底层驱动发包函数使用 mbuf 填充描述符
- 网卡获取到驱动填充的描述符后发起 PCIE 传输请求传输报文到内部 fifo 中
第一个过程需要操作报文的以太头,调用 l2fwd_simple_forward 函数前执行 rte_prefetch0 的意义就在这里。
报文以太头位于报文内容第一个 cache 行中,理想情况下在 l2fwd_simple_forward 函数访问以太头时,这个数据已经被预取到 cache 中,这样就减少了一次 cache miss。
这里存在的问题是在调用了 rte_prefetch 通知 cpu 预取指定的内存区域到 cpu 预取完成中间有一定的【时间窗口】,最理想的情况是在这个时间窗口中 cpu 一直在做其它事情,做完之后要访问预取的单元时,数据已经加载到 cache 中了。
但是要做到这种理想情况其实很难,可能在还没有预取完成前就访问了相关数据,这样可能还是会触发 cache miss,那软件预取语句实际上就没有任何意义了。
关闭硬件预取的尝试
在书上、网上看到的大部分资料都提到硬件预取能够提升程序运行的性能,但在真实的业务环境中到底提升了多少这一点就很少有相关的描述了。
那我们如何来评估硬件预取对性能提升的效果呢?
想想控制变量法的思路,只要保持其它条件不变,只开关硬件预取功能来测试性能就能够评估出来。可是几乎很少听到关闭硬件预取的信息,难道硬件预期根本不能关闭吗?
经过一些研究,发现在一些 intel 的高端 cpu 是支持通过 bios 配置关闭硬件预取的。在 C621 设备上(Intel® Xeon® Silver 4210 CPU)上观测 bios 配置,发现了如下相关配置项目:
第一项就是从各种计算机书中了解过的硬件预取功能,第二项中 RFO 的全称为(pipelined read-for-ownership operation)其功能目前没有深入研究,暂且跳过,第三项是相邻 cache 行预取功能,它假设用户已经请求了 64 字节的数据,实际上是想要 128-byte,它会多预取 64-byte 的数据来优化性能。
软件预取与硬件预取的适用场景
硬件预取适用于业务数据连续性访问占比高的场景,如桌面版系统,对于业务主要进行随机访问的场景,关闭硬件预取可能带来更高的性能。
intel 架构手册中提到的软件预取的适用场景如下:
- Predictable memory access patterns
- Time-consuming innermost loops
- Locations where the execution pipeline may stall if data is not availabl
总结
硬件预取耳熟能详,但是对它的印象主要停留在教科书的介绍中,在真实场景中的表现并不一定都能取得性能优化的效果。正如上文所指出的那样,当业务场景主要进行随机访问时,可能关闭硬件预取更好一些,不过还是需要实际的测试数据支撑来选择。
我想到一句话——要在不疑处存疑,硬件预取提升性能在许多人的印象中是不存在疑问的,但是这个印象更多的是来自书本的介绍,没有自己去实际的测试其实还是存在疑问的。发现这些疑问并做实验证明自己的猜测,排除任何的假设,用实际的测试数据说话,这一点相当重要,可能让我们发现一条新的道路。
参考链接
https://www.cs.cmu.edu/~binfan/papers/conext13_cuckooswitch.pdf
https://dev.dpdk.narkive.com/n9MgwnH9/dpdk-rte-prefetch0-performance-info
https://xem.github.io/minix86/manual/intel-x86-and-64-manual-vol3/o_fe12b1e2a880e0ce-846.html