【发布时间】:2016-10-20 02:05:12
【问题描述】:
在 x86 处理器上,有没有一种方法可以将数据从常规写回内存加载到寄存器中而无需通过缓存层次结构?
我的用例是我有一个大的查找结构(哈希图或 B 树)。我正在处理大量数字(比我的 L3 大得多,但适合内存)。我想做的很简单:
int result = 0;
for (num : stream_numbers) {
int lookup_result = lookup_using_b_tree(num);
result += do_some_math_that_touches_registers_only(lookup_result);
}
return result;
由于我只访问每个数字一次并且所有数字的总和大于 L3 大小,我想他们最终会驱逐一些包含我的 B-tree 部分的缓存行。相反,我希望这个流命中缓存中没有任何数字,因为它们根本没有时间局部性(只读取一次)。这样我可以最大限度地提高我的 B-tree 保留在缓存中的机会并且查找速度更快。
我查看了 SSE 4.1 中可用的 (v)movntdqa 指令,用于时间负载。这似乎不太合适,因为它似乎只适用于不可缓存的写入组合内存。这个来自英特尔的老article 声称:
未来几代英特尔处理器可能会针对流式加载进行优化和增强,例如提高流式加载缓冲区的利用率并支持其他内存类型,从而为软件开发人员创造更多机会来提高其性能和能源效率应用程序。
但是我今天不知道有任何这样的处理器。我已经读过elsewhere,处理器可以选择忽略这个回写内存的提示,而是使用movdqa。那么有什么方法可以在不通过 x86 处理器上的缓存层次结构的情况下从常规写回内存中实现负载,即使它只能在 Haswell 和更高版本的模型上实现?我也很感激有关将来是否有可能的任何信息?
【问题讨论】:
-
最近有人问了一个类似的问题,你可能也对this one感兴趣。
-
AFAIK 没有可靠/有保证的方法来做到这一点。
prefetchnta可能会有所帮助,但同样不清楚它是否可以做任何有用的事情,因为它不会覆盖 WB 内存类型的强排序缓存一致性语义。我认为你能期望的最好的结果是 prefetchnta 或 movntdqa 加载到缓存中并设置该行的 LRU 数据以表明它是一个很好的驱逐目标。因此,如果硬件确实以这种方式工作,那么一旦该流中的数据在每个集合中都有一个条目,希望该流中的数据只会从同一流中逐出之前的行。 -
如果您的数字的最终来源是文件或网络或程序外部的其他东西,您可能只想读取和处理更小块的数字。
-
@Rajiv: 不 :(。我的大部分知识都是理论知识,来自阅读文档/手册,而不是来自调整真实内容的实践经验。而且我不记得看到任何关于加速流媒体的内容从 WB 内存加载,只是存储。但就像我说的,我对微架构可以在 WB 内存上做什么的最佳猜测是设置缓存 LRU 数据,以便可以轻松地再次驱逐行。也许可以以某种方式测试这个猜测。跨度>
-
顺便说一下,这可能是一个有趣的阅读 - blog.stuffedcow.net/2013/01/ivb-cache-replacement。有可能您甚至不必为流式加载而烦恼,尽管当然只有基准测试才能证明这一点。
标签: assembly optimization x86 x86-64 cpu-cache