Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 以独占方式访问x86上的L1缓存线?_Performance_Assembly_X86_Cpu Cache_Low Level - Fatal编程技术网

Performance 以独占方式访问x86上的L1缓存线?

Performance 以独占方式访问x86上的L1缓存线?,performance,assembly,x86,cpu-cache,low-level,Performance,Assembly,X86,Cpu Cache,Low Level,如果有一个64字节的缓冲区被大量读/写,那么它很可能被保存在L1中;但有没有办法强迫这种行为 如中所示,为一个内核提供对这64个字节的独占访问,并告诉它不要与其他内核或内存控制器同步数据,以便这64个字节始终存在于一个内核的L1中,而不管CPU是否认为它使用得足够频繁。不,x86不允许这样做。您可以使用clfushot强制收回,或者(在即将推出的CPU上)只进行写操作而不使用clwb强制收回,但是您不能在缓存中固定行或禁用一致性 您可以将整个CPU(或单个内核?)放入缓存为RAM(也称为无填充

如果有一个64字节的缓冲区被大量读/写,那么它很可能被保存在L1中;但有没有办法强迫这种行为


如中所示,为一个内核提供对这64个字节的独占访问,并告诉它不要与其他内核或内存控制器同步数据,以便这64个字节始终存在于一个内核的L1中,而不管CPU是否认为它使用得足够频繁。

不,x86不允许这样做。您可以使用
clfushot
强制收回,或者(在即将推出的CPU上)只进行写操作而不使用
clwb
强制收回,但是您不能在缓存中固定行或禁用一致性


您可以将整个CPU(或单个内核?)放入缓存为RAM(也称为无填充)模式,以禁用与内存控制器的同步,并禁用任何回写数据的操作。它通常由BIOS/固件在配置内存控制器之前的早期引导中使用。它不是按行提供的,在这里几乎肯定没有实际用途。有趣的事实:离开此模式是的用例之一,它在不写回的情况下删除缓存数据,而不是
wbinvd

我不确定是否没有填充模式可以防止从L1d逐出到L3或其他任何模式;或者如果数据只是在逐出时丢弃的。因此,您只需避免访问7条以上的其他缓存线,这些缓存线与您在L1d中关心的缓存线或L2/L3的等效缓存线具有别名


如果能够强制一个核心无限期地挂在L1d线路上,而不响应MESI写回/共享该线路的请求,那么如果其他核心碰到该线路,就会容易被锁定。所以很明显,如果存在这样一个特性,它将需要内核模式。(对于硬件虚拟化,需要管理程序权限。)它还可以阻止硬件DMA(因为现代x86具有缓存一致性DMA)

因此,支持这样的功能需要CPU的许多部分来处理无限延迟,目前可能存在一些上限,如果存在这样的情况,可能会比PCIe超时短。(我不编写驱动程序或构建真正的硬件,只是猜测一下)

正如@fuz所指出的,一条违反一致性的指令(
xdcbt
)是错误的,错误推测指令的执行会导致灾难性的后果。所以很难实施


你通常不需要这个。 如果线路经常使用,更换LRU将使其保持热状态。如果它在足够频繁的时间间隔内从L1d丢失,那么它可能会在L2中保持热状态,在最近的设计中,L2也是核心和私有的,并且速度非常快(Intel自Nehalem以来)。除了Skylake-AVX512之外,Intel在CPU上的包容性L3意味着留在L1d中也意味着留在L3中

所有这一切都意味着,对于一条被一个内核大量使用的线路,在任何频率下,完全缓存未命中到DRAM的可能性都非常小。所以吞吐量应该不是问题我猜您可能希望实时延迟使用此选项,因为一次函数调用的最坏运行时间很重要。在代码的其他部分中,从缓存线进行虚拟读取有助于保持代码的热状态。

但是,如果来自三级缓存中其他内核的压力导致从三级缓存中逐出该行,则包含三级缓存的英特尔CPU还必须强制从仍处于热状态的内部缓存中逐出。IDK,如果有任何机制让L3知道一条线路在核心的L1d中被大量使用,因为这不会产生任何L3通信量

我不知道这在实际代码中是一个很大的问题。L3是高度关联的(比如16或24路),所以在你被驱逐之前需要很多冲突。L3还使用一个更复杂的索引函数(像一个真正的散列函数,而不仅仅是通过取一个连续的位范围进行模运算)。在IvyBridge和更高版本中,它还使用自适应替换策略来减少因接触大量不经常重用的数据而导致的逐出

另见


@亚历克西斯·威尔克指出,对于某些用例,您可以使用向量寄存器而不是缓存线。。您可以在全球范围内为此专门使用一些向量reg。要在gcc生成的代码中获得该值,可以使用或将其声明为易失性全局寄存器变量。()


使用ALU指令或存储转发向vector reg获取数据或从vector reg获取数据将为您提供有保证的延迟,而不存在数据缓存未命中的可能性。但是代码缓存未命中对于极低的延迟来说仍然是一个问题。

在Intel和AMD x86处理器上没有直接的方法来实现这一点,但是您可以通过一些努力来实现。首先,您说您担心缓存线可能会从一级缓存中移出,因为其他内核可能会访问它。这只能在以下情况下发生:

  • 线路是共享的,因此,系统中的多个代理可以同时访问该线路。如果另一个代理尝试读取该行,其状态将从“已修改”或“独占”更改为“共享”。也就是说,它将在L1中声明。另一方面,如果另一个代理试图写入该行,则必须从L1使其无效
  • 该行可以是私有的,也可以是共享的,但是该线程被操作系统重新安排在另一个内核上运行。与前一种情况类似,如果它尝试读取该行,其状态将在两个L1缓存中从修改或独占更改为共享。如果它试图写入该行,它必须从运行它的前一个内核的L1失效
正如我将在稍后讨论的那样,还有其他原因导致线路可能从L1中被逐出

如果行是共享的,则不能禁用一致性。但是,您可以做的是为它制作一个私有副本,这实际上会禁用一致性。如果这样做可能导致错误行为,那么您唯一能做的就是设置共享要运行的行的所有线程的关联性