【发布时间】:2011-02-07 20:50:12
【问题描述】:
我正在用 C++ 编写一个程序来执行特定系统的模拟。对于每个时间步,执行的最大部分是由单个循环占用。幸运的是,这是令人尴尬的并行,所以我决定使用 Boost Threads 来并行化它(我在 2 核机器上运行)。由于没有锁定,我希望加速接近串行版本的 2 倍。但是我发现根本没有加速。
我实现了循环的并行版本如下:
- 唤醒两个线程(它们被屏障阻塞)。
-
然后每个线程执行以下操作:
- 以原子方式获取和递增全局计数器。
- 检索具有该索引的粒子。
- 对该粒子执行计算,将结果存储在单独的数组中
- 等待作业完成障碍
主线程等待作业完成屏障。
我使用这种方法是因为它应该提供良好的负载平衡(因为每次计算可能需要不同的时间)。我真的很好奇是什么可能导致这种放缓。我总是读到原子变量很快,但现在我开始怀疑它们是否有性能成本。
如果有人有什么想法或任何提示,我将不胜感激。一个星期以来我一直在抨击它,但分析并没有透露太多。
编辑:问题解决了! 我将详细说明我是如何解决这个问题的。我再次使用 gprof,但这次编译时没有优化标志 (-O3)。立即,分析器表明我在对每个粒子执行计算的函数上花费了令人难以置信的时间:比在串行版本中要多得多。
这个函数是虚函数,可以多态访问。我更改了代码以直接访问它,而不是通过 vtable 和瞧,并行版本产生了将近 2 的加速!串行版本的相同更改几乎没有效果。
我不知道为什么会这样,如果有人知道的话会很感兴趣!
感谢所有的海报。你们都在一定程度上有所帮助,很难接受一个答案。
【问题讨论】:
-
有趣,您是否尝试过仅计时循环本身?是完全没有改善还是只是令人失望的改善?您是否在任务管理器中检查过您的应用程序实际上确实创建了两个线程?您的应用程序内存密集型是否可能遇到内存瓶颈?你也可以尝试简单的拆分数组,让每个线程处理一半,看看会不会有什么不同。
-
是的,我只对循环进行了计时和分析,没有别的。有一个令人失望的改进:加速范围从 0.9 到 1.1。任务管理器显示两个 cpu 都很忙。线程本身不分配任何新内存。唯一写入单个数组并且它们写入独立位置并且它们从不从同一个数组读取。当我将数组一分为二时,我得到了相似的性能。
标签: performance multithreading parallel-processing boost-thread atomic-values