如何在不污染缓存的情况下从内存加载值?

时间:2009-08-12 10:52:17

标签: assembly caching x86

我想在不污染缓存的情况下读取内存位置。我正在研究X86 Linux机器。我尝试使用MOVNTDQA汇编程序指令:

  asm("movntdqa %[source], %[dest] \n\t"
      : [dest] "=x" (my_var) : [source] "m" (my_mem[0]) : "memory");

my_mem是一个用new分配的int *,my_var是一个int。

这种方法有两个问题:

  1. 代码编译但运行时出现“非法指令”错误。有什么想法吗?
  2. 我不确定用new分配什么类型的内存。我会假设WB。根据文档,MOVNTDQA指令仅适用于USWC内存类型。我怎么知道我正在处理的内存类型?
  3. 总结一下,我的问题是:

    如何在不污染X86计算机缓存的情况下读取内存位置?我的方法是否朝着正确的方向发展,是否可以修复?

    感谢。

2 个答案:

答案 0 :(得分:7)

将%% xmm作为目标(从内存加载)的movntdqa指令的问题是此insn仅适用于SSE4.1及其。这意味着到目前为止只有较新的Core 2(45 nm)或i7。另一种方法(将数据存储到内存)在早期的SSE版本中可用。

对于此指令,处理器将数据移动到一个非常小的极少数读缓冲区中(英特尔没有指定确切的大小,但假设它在16字节的范围内),在那里它很容易获得,但是在其他一些负载之后被踢出去。

并且它不会污染其他缓存,因此如果您有流数据,那么您的方法是可行的。

请记住,之后你需要使用sfence insn。

预取存在两种变体:prefetcht0(预取所有高速缓存中的数据)和prefetchnt(预取非时态数据)。通常在所有缓存中进行预取是正确的做法,对于流式数据循环,后者会更好,如果你随后使用流式指令。

您可以将它与您想要在不久的将来使用的对象的地址一起使用,如果您有循环,通常会提前一些迭代。 prefetch insn不会等待或阻塞,只是让处理器开始在指定的内存位置获取数据。

答案 1 :(得分:0)

MOVNTDQA仅适用于SSE。

您为什么要避免使用缓存? CPU通常很擅长决定什么时候从缓存中踢出来。如果真的需要,一种方法是安排您正在读取的内存区域的别名被映射到您的地址空间,禁用缓存并从那里读取。

如果你想要实现的目的实际上是最小化代码对当时保存在缓存中的另一个函数的工作集的影响,那么通过发出适当的预取和无效指令应该可行。