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 在页面边界访问数据时速度是否减慢?_Performance_Memory_Cpu Architecture_Cpu Cache - Fatal编程技术网

Performance 在页面边界访问数据时速度是否减慢?

Performance 在页面边界访问数据时速度是否减慢?,performance,memory,cpu-architecture,cpu-cache,Performance,Memory,Cpu Architecture,Cpu Cache,(我的问题与计算机体系结构和性能理解有关。未找到相关论坛,因此将其作为一般问题发布在此处。) 我有一个C程序,可以访问虚拟地址空间中相隔X字节的内存字。例如,用于(inti=0;i+=X){array[i]=4;} 我使用变化的X值测量执行时间。有趣的是,当X是2的力量,并且大约是页面大小时,例如,X=1024204840968192…,我的性能会大大降低。但是在X的所有其他值上,如1023和1025,没有减速。性能结果如下图所示 我在几台个人计算机上测试了我的程序,它们都在英特尔CPU上运行

(我的问题与计算机体系结构和性能理解有关。未找到相关论坛,因此将其作为一般问题发布在此处。)

我有一个
C
程序,可以访问虚拟地址空间中相隔X字节的内存字。例如,
用于(inti=0;i+=X){array[i]=4;}

我使用变化的
X
值测量执行时间。有趣的是,当
X
2
的力量,并且大约是页面大小时,例如,
X=1024204840968192…
,我的性能会大大降低。但是在
X
的所有其他值上,如
1023
1025
,没有减速。性能结果如下图所示

我在几台个人计算机上测试了我的程序,它们都在英特尔CPU上运行x86_64的Linux

经济放缓的原因可能是什么?我们在DRAM、L3缓存等中尝试了行缓冲区,但似乎没有意义

更新(七月十一日)

我们在这里做了一个小测试,将NOP指令添加到原始代码中。经济放缓仍然存在。这类人否决了4k别名。冲突缓存未命中的原因更可能是这里的情况。

这里有两件事:

  • 如果只触摸4096个地址中的多个,则设置关联缓存别名以创建冲突未命中。内部快速缓存(L1和L2)通常由物理地址的小范围位索引。所以跨距4096字节意味着这些地址位对于所有访问都是相同的,所以您只是L1d缓存中的一个集合,而在L2中是一个小数目

    跨步1024意味着在L1d中只使用4个集合,2的较小幂次使用逐渐增多的集合,但非2的幂次分布在所有集合上。(英特尔CPU长期以来一直使用32KiB 8路关联L1d缓存;32K/8=4K/路。Ice Lake将其提升到48K 12路,因此相同的索引集只依赖于页码以下的位。对于希望与TLB并行索引的VIPT缓存来说,这不是巧合。)

    但是,使用非2次方跨步,您的访问将分布在缓存中的更多集合上。(答案描述了这一缺点)

    -共享三级缓存可以抵抗二次幂偏移量带来的混叠,因为它使用了更复杂的索引功能

  • 4k别名(例如,在某些英特尔CPU中)。虽然只有商店,但这可能并不重要。这主要是内存消除歧义的一个因素,当CPU必须快速确定某个负载是否可能正在重新加载最近存储的数据时,它只需查看页面偏移位,就可以在第一次加载时完成

    这可能不是为您所做的,但有关更多详细信息,请参阅:

这两种效应中的一种或两种都可能是导致死亡的因素


另一个可能的因素是硬件预取在物理页面边界处停止。但将步幅从1024改为1023并不能在很大程度上起到帮助作用。IvyBridge和更高版本中的“下一页”预取只是TLB预取,而不是下一页的数据


我对这个答案的大部分假设是x86,但缓存别名/冲突未命中的东西通常适用。具有简单索引的集合关联缓存普遍用于L1d缓存。(或在较旧的CPU上,直接映射,其中每个“集合”只有1个成员)。4k别名可能主要是英特尔特有的


跨虚拟页面边界的预取可能也是一个常见问题。

您可能需要说明它是哪个CPU(Intel Atom与Netburst非常不同,它们都与Sandy Bridge非常不同,Sandy Bridge与Haswell稍有不同;甚至同一micro arch中稍有不同的CPU型号也有不同的缓存大小),此外,如果页面已填充/存在,则阵列有多大(如果它太大,无法将所有的翻译放入CPU的TLB和/或某些缓存中)并且TLB被“加热”。对于一个随机猜测,我会怀疑某个地方存在混叠情况(可能是二级数据缓存?)。y轴代表什么?显示用于生成图形的整个代码,它是如何编译的,以及它在哪个CPU上运行的。我认为4k别名对于纯存储并不重要,只是存储和加载的混合。存储可以写入存储缓冲区,而不必计算它是否与较早或较晚的存储重叠。这就是我在a中说的原因在这里回答4k混叠可能无法解释这一点,尽管这通常是一个大步问题。是的,我同意原因可能是缓存未命中,并将更新OP。添加NOP不会显示任何内容。加载和存储不必背对背地发生4k混叠。如果不提供信息,则很难帮助您我在前面的评论中提到了这一点。循环中没有时间局部性,因此我认为缓存集映射几乎不重要(除非阵列的大小足够小,可以放入专用缓存,但足够大,可以写回,从而导致二级和三级端口的拥塞,从而可能影响性能)。阵列中显然没有加载,因此不会出现4K别名。硬件预取和TLB未命中的预期影响与OP中的图形不一致。虽然我怀疑OP显示的代码不是用于生成图形的代码。@HadiBrais:我假设这是在重复循环中,但这可能会导致错误这是一个错误的假设。我想知道,与其他较新的存储别名相同的存储是否会产生某种影响。例如,如果我们最终不得不等待写回,而我们不会这样做?或者可能提前收回硬件预取完成的一些加载,以便在存储提交之前必须重新加载?这可能会花费大量的时间很多时间。L1写回的优先级低于其他事务,因此它们是不可用的