我想将一些代码预取到指令缓存中。代码路径很少使用,但我需要它在指令缓存中,或者至少在 L2 中,因为它在极少数情况下使用。我提前通知了这些罕见的情况。_mm_prefetch 是否适用于代码?有没有办法在缓存中获取这个不经常使用的代码?对于这个问题,我不关心可移植性,所以即使 asm 也会这样做。
2 回答
答案取决于您的 CPU 架构。
也就是说,如果您使用 gcc 或 clang,您可以使用该__builtin_prefetch
指令来尝试生成预取指令。在 Pentium 3 和更高版本的 x86 型架构上,这将生成一条PREFETCHh
指令,该指令请求加载到数据缓存层次结构中。由于这些架构具有统一的 L2 和更高的缓存,因此可能会有所帮助。
该函数如下所示:
__builtin_prefetch(const void *address, int locality);
locality
参数应在 0...3 范围内。假设locality
直接映射到指令的h
一部分PREFETCHh
,您想要传递 1 或 2,这要求将数据加载到 L2 和更高的缓存中。请参阅英特尔® 64 和 IA-32 架构软件开发人员手册第 2B 卷:指令集参考,MZ (PDF)第 4-277 页。(在此处查找其他卷。)
如果您正在使用另一个没有 的编译器__builtin_prefetch
,请查看它是否具有该_mm_prefetch
功能。您可能需要包含一个头文件才能获得该功能。例如,在 OS X 上,该函数和locality
参数的常量在xmmintrin.h
.
没有任何(官方 [1] x86)指令来预取代码,只有数据。我发现这是一个相当奇怪的用例,其中代码路径是事先知道的,但很少执行,并且预取代码有很大的好处。很高兴了解您在哪里得出的结论,即为这种特殊情况预加载代码有很大的好处,因为它不仅需要分析代码在没有被命中时显着变慢很长一段时间,但还要确定在处理器可以通过其正常的加载代码机制预取代码之前实际加载代码的空闲总线周期。
您也许可以使用prefetch
获取 L2 的指令,该指令通常在 I 和 D 缓存之间共享。
[1] 我知道有一些“秘密”指令允许处理器操作缓存内容,但由于这些指令需要大量额外的工作,即使您可以在用户模式代码中使用它们[我希望这是不是一些内核模式代码]。