只读内存访问的线程安全性

Edm*_*und 4 c pthreads thread-safety

我在C中实现了Barnes-Hut重力算法如下:

  1. 建立一群星团.
  2. 对于每颗恒星,遍历树并应用每个适用节点的重力.
  3. 更新恒星速度和位置.

阶段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
Run Code Online (Sandbox Code Playgroud)

0表示根本没有线程; 1及以上意味着产生许多工作线程和主线程等待它们.我不希望超过2个线程的任何改进,因为它完全受CPU限制,而且有多少个核心.有趣的是,奇数个线程比偶数更差.

看着sys它显然是制作线程的成本.目前它正在为每个帧创建线程(因此N*1000线程创建).这很容易编程(今天早上我在火车上的15分钟).我需要考虑一下如何重用线程......

更新#2我使用了一个线程池,与两个障碍同步.与每帧重新创建线程相比,这没有明显的性能优势.

Ste*_*art 7

您没有指定数据的结构,但通常从多个线程同时读取内存是安全的,并且不会引入任何性能问题.如果有人写作,你只会遇到问题.

有趣的是,你说你的两个线程只能获得30%的加速.如果你有一台空闲的机器,两个或多个CPU,只有只读共享数据(即没有同步),我预计会有更接近50%的速度提升.这表明您的操作实际上很快完成,创建线程的开销在您的数字中变得非常重要.你是在超线程CPU上运行吗?