我的任务是编写一个程序,以尽可能绝对的最大速度将矢量流传输到分散的存储器位置。输入数据是目标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}
更复杂的是,会有多个线程同时执行此操作,从不同的输入流读取但总结到相同的内存。我预计相同的内存位置不会有很多争用,但会有一些。数据集将非常大 - 每个10 GB以上的多个流,我们将同时从多个SSD流式传输以获得尽可能高的读取带宽。我假设SSE用于数学,虽然它肯定不一定是这样。
结果暂时不会使用,所以我不需要污染缓存...但我总结成内存,而不仅仅是写入,所以我不能使用像MOVNTPS这样的东西,对吧?但是由于线程不会相互踩得那么多,如何在没有大量锁定开销的情况下做到这一点呢?你会用内存防护吗?
感谢您的帮助。我可以假设Nehalem及以上,如果这有所不同。
答案 0 :(得分:0)
您可以使用自旋锁来同步访问数组元素(每个ID一个)和SSE进行求和。在C ++中,取决于编译器,内部函数可以是可用的,例如, Visual C ++中的Streaming SIMD Extensions和InterlockExchange。
答案 1 :(得分:0)
您的程序性能将受到内存带宽的限制。除非您拥有多CPU(不仅仅是多核)系统,否则不要指望多线程可以显着提高速度。
每个CPU启动一个线程。在这些线程之间静态分发目标数据。并为每个线程提供相同的输入数据。这样可以更好地使用NUMA架构。并避免了线程同步的额外内存流量。
对于单CPU系统,只使用一个线程访问目标数据。
可能在CPU中使用更多内核的唯一实际用途是使用额外的线程加载输入数据。
一个明显的优化是将目标数据对齐16个字节(以避免在访问单个数据元素时触摸两个缓存行)。
您可以使用SIMD执行添加,或者允许编译器自动对您的代码进行矢量化,或者让这个操作完全不受优化 - 这没关系,与内存带宽问题相比没什么。
对于使用输出数据污染缓存,MOVNTPS在这里无法提供帮助,但您可以使用PREFETCHNTA预先提取输出数据元素,同时最大限度地减少缓存污染。我不知道会改善性能还是降低性能。它避免了缓存垃圾,但是大部分缓存都没有使用。