我正在尝试在linux上使用WBINV指令来清除处理器的L1缓存.
以下程序编译,但在我尝试运行它时会产生分段错误.
int main() {asm ("wbinvd"); return 1;}
我正在使用gcc 4.4.3并在我的x86机器上运行Linux内核2.6.32-33.
处理器信息:Intel(R)Core(TM)2 Duo CPU T5270 @ 1.40GHz
我按如下方式构建了该程序:
$ gcc
$ ./a.out
分段故障
谁能告诉我我做错了什么?我如何让它运行?
PS:我正在运行一些性能测试,并希望确保处理器缓存的先前内容不会影响结果.
我对OS没有偏好; 任何工具都可以,只要它允许我测量Core 2和i7架构上的缓存性能.
假设我知道以下值:
W = Word length (= 32 bits)
S = Cache size in words
B = Block size in words
M = Main memory size in words
Run Code Online (Sandbox Code Playgroud)
如何计算需要多少位:
- Index
- Block offset
- Byte offset
- Tag
Run Code Online (Sandbox Code Playgroud)
a)在完全关联缓存中的直接映射缓存b)?
在Jim Handy的高速缓冲存储器书中(摘录如下),作者有MESI协议的表格描述.该表对我来说看起来很不清楚,不幸的是文本没有帮助.
第一个问题(图中绿色):
Is this right? -- a data block is in the cache of a CPU,
and it is in the shared state, but when the CPU reads it,
the CPU gets read miss.
How is this possible?
Run Code Online (Sandbox Code Playgroud)
第二个问题(紫色):
Who and when create all these messages "Read miss", etc.?
(afaik, the system bus just translates messages of others)
Run Code Online (Sandbox Code Playgroud)
最后,第三个问题(不在图片上):
Do all these cache coherency protocols
(MSI,MESI,MOESI,Firefly,Dragon...)
maintain sequential consistency memory model?
Are there protocols that maintain other consistency models?
Run Code Online (Sandbox Code Playgroud)

我已经读过这个主题:C#Thread safe fast(est)计数器,并在我的并行代码中实现了这个功能.据我所知,它一切正常,但它的处理时间明显增加,大约10%左右.
它一直困扰着我,我认为问题在于我在小数据片段上做了大量相对便宜(<1量子)的任务,这些片段很好地分配并可能充分利用缓存局部性,从而以最佳方式运行.根据我对MESI的了解,我最好的猜测是,x86 LOCK前缀Interlocked.Increment将高速缓存行推入独占模式,并强制其他内核上的高速缓存未命中,并强制高速缓存重新加载每个并行传递,只是为了增加此计数器.有100ns-ish延迟缓存未命中和我的工作量似乎加起来.(然后,我可能是错的)
现在,我没有看到解决方法,但也许我错过了一些明显的东西.我甚至考虑使用n个计数器(对应于并行化程度),然后在特定核心上递增每个,但是它似乎不可行(检测我所使用的核心可能会更昂贵,更不用说详细的if/then/else结构和搞乱执行管道).关于如何打破这头野兽的任何想法?:)
考虑N线程执行一些具有小结果值的异步任务,如double或int64_t.因此,8结果值可以适合单个CPU缓存行.N等于CPU核心数.
一方面,如果我只是分配一个N项目数组,每个a double或者int64_t,那么8 线程将共享一个CPU缓存行,这似乎效率低下.
另一方面,如果我为每个double/ 分配一个完整的缓存行int64_t,接收器线程将必须获取N缓存行,每个缓存行由不同的CPU核心(1除外)写入.
那么这种情况是否有效的解决方案?CPU是x86-64.C++中的解决方案是首选.
澄清1:线程启动/退出开销不大,因为使用了线程池.所以它主要是关键部分的同步.
澄清2:并行批次具有依赖性.主线程只能在收集并处理上一批次的结果后才能启动下一批并行计算.因为前一批次的结果用作下一批次的一些参数.
英特尔手动优化(2019 年 9 月修订版)显示了用于 Ice Lake 微架构的 48 KiB 8 路关联 L1 数据缓存。
这让我感到困惑,因为:
总而言之,缓存的处理成本似乎更高,但延迟仅略有增加(如果确实如此,则取决于英特尔对该数字的确切含义)。
有一点创造力,我仍然可以想象一种快速索引 96 组的方法,但第二点对我来说似乎是一个重要的突破性变化。
我错过了什么?
我正在阅读 MDS 攻击论文RIDL:Rogue In-Flight Data Load。他们讨论了 Line Fill Buffer 如何导致数据泄漏。有关于 RIDL 漏洞和负载的“重放”问题讨论了漏洞利用的微架构细节。
阅读该问题后,我不清楚的一件事是,如果我们已经有了存储缓冲区,为什么还需要行填充缓冲区。
John McCalpin 在WC-buffer 与LFB 有什么关系?中讨论了存储缓冲区和行填充缓冲区是如何连接的?在英特尔论坛上,但这并没有真正让我更清楚。
对于存储到 WB 空间,存储数据将保留在存储缓冲区中,直到存储退出之后。退役后,数据可以写入 L1 数据缓存(如果该行存在且具有写入权限),否则会为存储未命中分配一个 LFB。LFB 最终会收到缓存行的“当前”副本,以便它可以安装在 L1 数据缓存中,并且可以将存储数据写入缓存。合并、缓冲、排序和“捷径”的细节尚不清楚......与上述合理一致的一种解释是 LFB 用作缓存行大小的缓冲区,其中存储数据在发送到L1 数据缓存。至少我认为这是有道理的,但我可能忘记了一些事情......
我最近才开始阅读乱序执行,所以请原谅我的无知。这是我关于商店如何通过商店缓冲区和行填充缓冲区的想法。
这是一个边缘话题。因为我想了解编程、CPU 缓存、读取 CPU 缓存行等,所以我把它贴在这里。
我在 C/C++ 中实现了 AES 算法。由于在没有硬件支持的情况下执行 GF(2 8 ) 乘法在计算上是昂贵的,我已经优化为使用 AES S-box 的查找表。但不幸的是,基于查找表的实现容易受到缓存定时攻击。因此,由于对 CPU 缓存非常天真,我开始学习它的工作原理,以及如何在不增加任何计算成本的情况下规避这种攻击。
我意识到实际上有 AES NI 指令和 Bit Slice AES 实现,但它们远远超出了我目前的理解。
我从 crypto.SE 了解到,最简单的方法是在查找之前读取所有缓存行或读取整个表。(这也影响了我的表现)但是我不知道如何在软件中实现它,或者它背后的复杂概念。
在OpenSSLaes-x86core.c的C 实现参考指南中—— 作者实现了一个功能:
static void prefetch256(const void *table)
{
volatile unsigned long *t=(void *)table,ret;
unsigned long sum;
int i;
/* 32 is common least cache-line size */
for (sum=0,i=0;i<256/sizeof(t[0]);i+=32/sizeof(t[0])) sum ^= t[i];
ret = sum;
}
Run Code Online (Sandbox Code Playgroud)
for循环i中增加8 …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 个周期。