2

我的任务是编写一个程序,以可能的绝对最大速度将向量总和流式传输到分散的内存位置。输入数据是一个目标 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 及以上,如果这有所作为。

4

2 回答 2

0

您可以使用自旋锁同步访问数组元素(每个 ID 一个)和 SSE 进行求和。在 C++ 中,根据编译器的不同,可能会提供内在函数,例如 Visual C++ 中的Streaming SIMD ExtensionsInterlockExchange

于 2012-01-29T00:09:20.957 回答
0

您的程序的性能将受到内存带宽的限制。除非您拥有多 CPU(而不仅仅是多核)系统,否则不要期望多线程能够显着提高速度。

每个 CPU 启动一个线程。在这些线程之间静态分配目标数据。并为每个线程提供相同的输入数据。这允许更好地使用 NUMA 架构。并避免线程同步的额外内存流量。

在单 CPU 系统的情况下,仅使用一个线程访问目标数据。

可能,CPU 中更多内核的唯一实际用途是使用额外线程加载输入数据。

一项明显的优化是将目标数据对齐 16 个字节(以避免在访问单个数据元素时接触两个高速缓存行)。

您可以使用 SIMD 来执行加法,或者允许编译器自动矢量化您的代码,或者完全不优化此操作 - 没关系,与内存带宽问题相比,这算不了什么。

至于输出数据污染缓存,MOVNTPS 在这里帮不上忙,但您可以使用 PREFETCHNTA 提前几步预取输出数据元素,同时最大限度地减少缓存污染。我不知道它会提高性能还是降低性能。它避免了缓存垃圾,但使大部分缓存未使用。

于 2012-01-29T11:12:04.223 回答