【发布时间】:2019-06-18 11:29:41
【问题描述】:
我正在考虑执行以下操作:
- 编写一个守护进程,创建大约 50KB 的引用数据并将其存储在共享内存中的数组中。
- 守护进程将其亲和性设置为套接字上的一个核心,并定期在引用数据的第 64 个字节的地址上调用
__builtin_prefetch(),以将所有引用数据保留在 L3 缓存中以供所有进程运行在同一插槽上的其他内核上。 - 每秒多次,应用程序进程将索引到数组中以检索他们当时需要的任何参考数据。由于数据将在 L3 缓存中,因此访问时间会相对较快。
我想我不是第一个提出这种想法的人。有人可以就我可能遇到的限制提供建议吗?例如,在守护进程中考虑以下伪代码,用于将参考数据保存在缓存中:
for (size_t i = 0; i < sizeof(referenceData); i += 64) {
__builtin_prefetch(i + (void*)&referenceData);
}
对于 50KB 的参考数据,上述循环将快速连续调用 __builtin_prefetch() 800 次。这样做会导致问题,例如当其他应用程序尝试访问内存(参考数据除外)时出现延迟峰值吗?如果是这样,我可以在 for 循环中插入一个 sleep 语句:
for (size_t i = 0; i < sizeof(referenceData); i += 64) {
__builtin_prefetch(i + (char*)&referenceData);
if (i % (64*10)) { // sleep every 10th time around the loop
sleep_briefly();
}
}
感谢您提供相关文件来源的建议和链接。
编辑以添加基于 cmets 的附加信息:
参考数据将保持不变。其他进程将访问 应用程序级事件中数据的一小部分:可能大约 数据中有 7 个索引,每个索引检索 4 个字节,因此 每个事件检索大约 28 个字节。
我认为无法预测哪些数据条目最有可能被访问,因此我希望将整个参考数据保留在缓存中,而不仅仅是其中的一小部分。
如果延迟无关紧要,则不需要缓存的参考数据,因为每个应用程序都可以根据需要为每个事件重新计算所需的任何内容。但是,响应事件的延迟确实很重要。
我还没有开发出所有的应用程序代码,但我希望“响应事件”的时间小于 200ns 这个优化。如果这种优化效果很好,那么它可能会将“响应事件”的时间缩短到 100ns 以下。
事件的发生频率可能高达每秒几百次,也可能每隔几秒发生一次。所以我担心的是,如果参考数据没有在缓存中主动保温,偶尔会因为使用不足而被刷出缓存。
【问题讨论】:
-
参考数据是随时间变化还是保持不变?其他进程多久访问一次它?访问参考数据是瓶颈吗?
-
这整个设置基本上是试图无缘无故地干预缓存预取。是什么让你认为你首先需要这个?如果 "Multiple times per second" 是数百万次,则该数据很可能会在缓存中,无需任何手动帮助。如果只是几次,那么几次缓存未命中就无关紧要了。
-
@Maxim Egorushkin:我已经编辑了我的问题以提供额外信息。
-
@VTT:我已经编辑了我的问题以提供额外信息。
-
您的 CPU 在事件之间是否空闲?除非他们进入非常深度的睡眠(并完全关闭他们的缓存),否则数据将保持热状态,除非有其他东西使其无效。不过,这可能包括中断处理程序。