【发布时间】:2012-02-21 09:08:48
【问题描述】:
我的任务是编写一个程序,以可能的绝对最大速度将向量总和流式传输到分散的内存位置。输入数据是一个目标 ID 和一个 XYZ 浮点向量,如下所示:
[198, {0.4,0,1}], [775, {0.25,0.8,0}], [12, {0.5,0.5,0.02}]
我需要像这样将它们汇总到内存中:
memory[198] += {0.4,0,1}
memory[775] += {0.25,0.8,0}
memory[12] += {0.5,0.5,0.02}
更复杂的是,将有多个线程同时执行此操作,从不同的输入流读取但汇总到相同的内存。我预计不会有很多争用相同的内存位置,但会有一些。数据集将非常大 - 我们将同时从多个 SSD 流式传输每个 10+ GB 的多个流,以获得尽可能高的读取带宽。我假设数学是 SSE,尽管它当然不必是这样。
结果暂时用不上,所以不需要污染缓存……不过我是在内存中求和,不只是写,所以不能用MOVNTPS之类的东西,对吧?但是由于线程不会互相踩踏那么多,我怎么能在没有大量锁定开销的情况下做到这一点?你会用内存围栏来做这个吗?
感谢您的帮助。我可以假设 Nehalem 及以上,如果这有影响的话。
【问题讨论】:
-
我假设您访问的是内存中的一个紧密排列的数组。由于每个元素的宽度是 3 个浮点数,因此大多数元素不会与 16 字节边界对齐,这使得 SSE 移动非常缓慢。此外,正如您的示例所暗示的,数据访问背后没有简单的模式,因此很难预取。总之,这将使上交所的潜力难以发挥。可能最好的猜测是简单地在 C/++ 中执行此操作并让编译器发挥作用,我怀疑使用 SIMD 改进这一点的可能性有很多。
-
我可以在内存中使用 4-float 向量来毫无问题地获得 16-bit 对齐。预取在这里有什么帮助?这肯定会使求和变得更容易,但是预取+求和+写使我面临各种竞争条件,而其他线程也在做同样的事情。
-
预取内存时对齐无关紧要,但如果不是,您将不得不使用未对齐移动或确保数据对齐,当您访问元素所在的密集排列的数组时,您不能这样做有 3 个花车宽。