我正在用 C++ 编写一个程序来执行特定系统的模拟。对于每个时间步,执行的最大部分是由单个循环占用。幸运的是这是令人尴尬的并行,所以我决定使用 Boost Threads 来并行化它(我在 2 核机器上运行)。由于没有锁定,我希望加速接近串行版本的 2 倍。但是我发现根本没有加速。
我实现了循环的并行版本,如下所示:
- 唤醒两个线程(它们被阻塞在屏障上)。
然后每个线程执行以下操作:
- 原子地获取并增加一个全局计数器。
- 检索具有该索引的粒子。
- 对该粒子执行计算,将结果存储在单独的数组中
- 等待工作完成障碍
主线程等待作业完成屏障。
我使用这种方法是因为它应该提供良好的负载平衡(因为每次计算可能需要不同的时间)。我真的很好奇是什么可能导致这种放缓。我总是读到原子变量很快,但现在我开始怀疑它们是否有性能成本。
如果有人有一些想法要寻找什么或任何提示,我将不胜感激。我一直在抨击它一个星期,并且分析并没有透露太多。
编辑:问题解决了! 我将详细说明我是如何解决这个问题的。我再次使用 gprof,但这次编译时没有优化标志 (-O3)。立即,分析器表明我在对每个粒子执行计算的函数上花费了令人难以置信的时间:比在串行版本中要多得多。
这个函数是虚拟的,可以多态访问。我更改了代码以直接访问它,而不是通过 vtable 和瞧,并行版本产生了近 2 的加速!串行版本的相同更改几乎没有效果。
我不确定为什么会这样,如果有人知道,我会很感兴趣!
感谢所有的海报。你们都在一定程度上有所帮助,很难接受一个答案。