不,x86 不允许您这样做。您可以使用 clfushopt 强制驱逐,或者(在即将推出的 CPU 上)仅使用 clwb 进行回写而不驱逐,但您不能将行固定在缓存中或禁用一致性。
您可以将整个 CPU(或单个内核?)置于缓存即 RAM(也称为无填充)模式,以禁用与内存控制器的同步,并禁止回写数据。 Cache-as-Ram (no fill mode) Executable Code。它通常由 BIOS / 固件在配置内存控制器之前的早期启动中使用。它不是按行提供的,而且几乎可以肯定在这里实际上没有用。有趣的事实:离开此模式是 invd 的用例之一,它在不写回的情况下删除缓存数据,而不是 wbinvd。
我不确定无填充模式是否会阻止从 L1d 驱逐到 L3 或其他什么;或者如果数据只是在驱逐时丢弃。因此,您只需避免访问 7 个以上的其他缓存行,这些缓存行是您在 L1d 中关心的缓存行的别名,或 L2/L3 的等效缓存行。
如果能够强制一个内核无限期地挂在 L1d 行上,而不响应 MESI 将其写回/共享的请求,这将使其他内核在触及该行时容易被锁定。所以很明显,如果存在这样的功能,它将需要内核模式。 (并且使用硬件虚拟化,需要管理程序权限。)它还可以阻止硬件 DMA(因为现代 x86 具有缓存一致的 DMA)。
因此,支持这样的功能需要 CPU 的许多部分来处理无限期延迟,目前可能存在一些上限,如果存在这样的情况,它可能比 PCIe 超时更短。 (我不编写驱动程序或构建真正的硬件,只是猜测)。
正如@fuz 所指出的,违反一致性的指令 (xdcbt) 是 tried on PowerPC (in the Xbox 360 CPU),错误推测的指令执行会导致灾难性的后果。所以实现起来困难。
你通常不需要这个。
如果线路经常使用,更换 LRU 会使其保持热度。如果它以足够频繁的间隔从 L1d 丢失,那么它可能会在 L2 中保持热状态,这也是核心和私有的,并且在最近的设计中非常快(自 Nehalem 以来的英特尔)。英特尔在 Skylake-AVX512 以外的 CPU 上的包容性 L3 意味着留在 L1d 也意味着留在 L3。
所有这一切都意味着,对于一个内核大量使用的线路,无论以何种频率,都不太可能出现完全缓存未命中到 DRAM 的情况。所以吞吐量应该不是问题。 我想您可能希望将其用于实时延迟,在这种情况下,一次函数调用的最坏情况运行时间很重要。在代码的其他部分从缓存行进行虚拟读取可能有助于保持其热度。
但是,如果来自 L3 缓存中其他内核的压力导致该行从 L3 中逐出,则具有包容性 L3 的 Intel CPU 也必须强制从仍然热的内部缓存中逐出。 IDK 如果有任何机制让 L3 知道某条线路在核心的 L1d 中被大量使用,因为这不会产生任何 L3 流量。
我不知道这在实际代码中是一个很大的问题。 L3 具有高度关联性(如 16 或 24 路),因此在您被驱逐之前需要很多冲突。 L3 还使用了一个更复杂的索引函数(就像一个真正的散列函数,而不仅仅是通过取一个连续的位范围来取模)。在 IvyBridge 及更高版本中,它还使用自适应替换策略来减少因接触大量不会经常重用的数据而被驱逐。 http://blog.stuffedcow.net/2013/01/ivb-cache-replacement/.
另见Which cache mapping technique is used in intel core i7 processor?
@AlexisWilke 指出 对于某些用例,您可以使用向量寄存器而不是缓存行。 Using ymm registers as a "memory-like" storage location。您可以为此目的在全球范围内专门使用一些向量 reg。要在 gcc 生成的代码中获取此信息,可以使用 -ffixed-ymm8,或者将其声明为 volatile 全局寄存器变量。 (How to inform GCC to not use a particular register)
使用 ALU 指令或存储转发从向量 reg 获取数据或从向量 reg 获取数据将为您提供有保证的延迟,而不会出现数据缓存未命中的可能性。但是对于极低的延迟,代码缓存未命中仍然是一个问题。