相关疑难解决方法(0)

了解std :: hardware_destructive_interference_size和std :: hardware_constructive_interference_size

C++ 17添加std::hardware_destructive_interference_size和std::hardware_constructive_interference_size.首先,我认为这只是获取L1缓存行大小的可移植方式,但这是过于简单化.

问题:

  • 这些常量如何与L1缓存行大小相关?
  • 是否有一个很好的例子来演示他们的用例?
  • 两者都是定义的static constexpr.如果您构建二进制文件并在具有不同缓存行大小的其他计算机上执行它,这不是问题吗?当您不确定您的代码将运行在哪台机器上时,如何防止错误共享?

c++ concurrency c++17

64
推荐指数
2
解决办法
4605
查看次数

预取L1和L2的数据

在Agner Fog的手册" C++中的优化软件 "第9.10节"大数据结构中的Cahce争论"中,他描述了当矩阵宽度等于称为临界步幅的情况时转置矩阵的问题.在他的测试中,当宽度等于临界步幅时,L1中矩阵的成本增加40%. 如果矩阵更大并且仅适用于L2,则成本为600%! 这在表9.1中的文字中得到了很好的总结.这与在为什么将512x512的矩阵转置比转置513x513的矩阵要慢得多一样是必不可少的 ?

后来他写道:

这种效果对于二级高速缓存争用而言比一级高速缓存争用强得多的原因是二级高速缓存不能一次预取多行.

所以我的问题与预取数据有关.

根据他的评论,我推断L1可以一次预取多个缓存行. 预取了多少?

据我所知,尝试编写代码来预取数据(例如使用_mm_prefetch)很少有用.我读过的唯一例子是Prefetching Examples?它只有O(10%)的改进(在某些机器上).Agner后来解释了这个:

原因是现代处理器由于无序执行和高级预测机制而自动预取数据.现代微处理器能够自动预取包含具有不同步幅的多个流的常规访问模式的数据.因此,如果可以使用固定步幅以常规模式排列数据访问,则不必显式预取数据.

那么CPU如何决定预取哪些数据,以及有哪些方法可以帮助CPU为预取做出更好的选择(例如"具有固定步幅的常规模式")?

编辑:根据Leeor的评论,让我添加我的问题并使其更有趣. 与L1相比,为什么关键步幅对L2的影响要大得多?

编辑:我试图使用代码重现Agner Fog的表格为什么转换512x512的矩阵要比转置513x513的矩阵慢得多? 我在Xeon E5 1620(Ivy Bridge)上以MSVC2013 64位版本模式运行它,它具有L1 32KB 8路,L2 256 KB 8路和L3 10MB 20路.L1的最大矩阵大小约为90x90,L3为256x256,L3为1619.

Matrix Size  Average Time
64x64        0.004251 0.004472 0.004412 (three times)
65x65        0.004422 0.004442 0.004632 (three times)
128x128      0.0409
129x129      0.0169
256x256      0.219   //max L2 matrix size
257x257      0.0692
512x512      2.701
513x513      0.649
1024x1024    12.8
1025x1025    10.1
Run Code Online (Sandbox Code Playgroud)

我没有看到L1中的任何性能损失,但是L2明显具有关键的步幅问题,可能是L3.我不确定为什么L1没有出现问题.有可能还有一些其他的背景源(开销)占据了L1时代的主导地位.

c cpu x86 cpu-cache

13
推荐指数
1
解决办法
5056
查看次数

在什么情况下会触发基于 L1 IP 的跨距预取器?

Intel 硬件预取器 Intel 网站显示有四种硬件预取器。由第 3 位控制的预取器是 L1 步幅预取器。我正在运行一个测试代码来测试 stride 预取器的触发条件是什么。我按照以下步骤运行代码(将 MSR0x1a4 设置为 0x7,这意味着仅启用基于 L1 IP 的 strider 预取器):

repeat following for 10000 times:
    flush
    training phase: access line 0 3 6 9 
    sleep for near 1000 cycles
    measure phase: measure line 12
Run Code Online (Sandbox Code Playgroud)

我希望看到第 12 行被预取到缓存中。但是我只能看到缓存中的第 0 3 6 9 行被命中。即使我更改了步幅或访问模式的长度,也无法观察到步幅预取活动。所以我想知道是否有人在英特尔处理器中看到过预取活动,或者有一些我没有注意到的特殊触发条件?

对这个案例有兴趣的可以试一下测试代码。运行sudo ./run.sh就可以了。我的机器上的结果显示,第 12 行的访问时间大多大于 180 个周期。我认为时间测量代码没有问题,因为如果我将测量的行从缓存行 12 更改为缓存行 6(只需在 test.c,第 103 行更改),那么访问时间主要是 25 个周期。

x86 intel prefetch cpu-cache micro-architecture

7
推荐指数
0
解决办法
82
查看次数

标签 统计

cpu-cache ×2

x86 ×2

c ×1

c++ ×1

c++17 ×1

concurrency ×1

cpu ×1

intel ×1

micro-architecture ×1

prefetch ×1