我在C中实现了Barnes-Hut重力算法,如下所示:
阶段2是最昂贵的阶段,因此通过划分星组来并行实施。例如。有1000颗星和2个线程,我有一个线程处理前500颗星,第二个线程处理第二个500颗。
在实践中,这是有效的:与非线程版本相比,在双核机器上使用两个线程可以将计算速度提高约30%。此外,它产生与原始非线程版本相同的数值结果。
我担心的是两个线程同时访问相同的资源(即树)。我没有向线程工作者添加任何同步,因此他们可能会尝试在某个时刻从同一位置读取。虽然访问树是严格只读的,但我并不是100%确定它是安全的。它在我测试它时起作用,但我知道这不能保证正确性!
问题
更新好奇的基准测试结果:
机器:Intel Atom CPU N270 @ 1.60GHz,cpu MHz 800,缓存大小512 KB
Threads real user sys
0 69.056 67.324 1.720
1 76.821 66.268 5.296
2 50.272 63.608 10.585
3 55.510 55.907 13.169
4 49.789 43.291 29.838
5 54.245 41.423 31.094
0表示根本没有线程; 1及以上意味着产生许多工作线程和主线程等待它们。我不希望超过2个线程的任何改进,因为它完全受CPU限制,而且有多少核心。有趣的是,奇数个线程比偶数更差。
看sys
,显然制作线程需要付出代价。目前它正在为每个帧创建线程(因此N * 1000线程创建)。这很容易编程(今天早上我在火车上的15分钟)。我需要考虑一下如何重用线程...
更新#2 我已经使用了一个线程池,与两个障碍同步。与每帧重新创建线程相比,这没有明显的性能优势。
答案 0 :(得分:7)
您没有指定数据的结构,但通常从多个线程同时读取内存是安全的,并且不会引入任何性能问题。如果有人写作,你只会遇到问题。
有趣的是,你说你的两个线程只能获得30%的加速。如果你有一台空闲的机器,两个或多个CPU,只有只读共享数据(即没有同步),我预计会有更接近50%的速度提升。这表明您的操作实际上很快完成,创建线程的开销在您的数字中变得非常重要。你是在超线程CPU上运行吗?
答案 1 :(得分:4)
如果您的数据是只读的,那么不需要,您不需要为每个线程制作树的私有副本。这是共享内存线程模型提供的最大优势!
我不知道这种模型有任何性能问题。如果有的话,它应该更快,这取决于你的CPU是否可以共享一些缓存。