在我的应用程序中,我有一个for循环运行大约一千万个项目,如下所示:
int main(int argc, char* argv [])
{
unsigned int nNodes = 10000000;
Node** nodeList = new Node* [nNodes];
initialiseNodes(nodeList); // nodes are initialised here
for (unsigned int ii = 0l ii < nNodes; ++ii)
nodeList[ii]->update();
showOutput(nodeList) // show the output in some way
}
我不会详细介绍如何精确初始化或显示节点。重要的是Node::update()
方法是一种小方法,独立于其他节点。因此,并行地执行该循环将是非常有利的。由于它只是一件小事,我想这次远离OpenCL / CUDA / OpenMP,所以我使用了C ++ Concurrency::parallel_for
。那么代码就像这样:
#include <ppl.h>
int main(int argc, char* argv [])
{
unsigned int nNodes = 10000000;
Node** nodeList = new Node* [nNodes];
initialiseNodes(nodeList); // nodes are initialised here
Concurrency::parallel_for(unsigned int(0), nNodes, [&](unsigned int ii) {
nodeList[ii]->update();
});
showOutput(nodeList) // show the output in some way
}
这确实加快了程序的速度,但通常只有20%左右,我发现。坦率地说,我期待更多。在使用parallel_for
时,有人可以告诉我这是否是典型的加速因素?或者有没有办法从中获得更多(没有切换到GPU实现)?
答案 0 :(得分:1)
在问题上投入更多内核并不总能带来改进。事实上,在最坏的情况下,它甚至可以降低性能。从使用多个内核中受益取决于许多因素,例如涉及的共享数据量。有些问题本质上是可并行化的,有些则不是。
答案 1 :(得分:0)
我发现我认为对性能提升的贡献最大。当然,像@ anthony-burleigh所说,任务必须是可并行的,共享数据的影响也是如此。然而,我发现并行化方法的计算负荷更重要。大任务似乎比小任务提供更高的加速。
例如,在:
Concurrency::parallel_for(unsigned int(0), nNodes, [&](unsigned int ii) {
nodeList[ii]->update(); // <-- very small task
});
我的加速因子只有1.2。但是,在一项繁重的任务中,例如:
Concurrency::parallel_for(unsigned int(0), nNodes, [&](unsigned int ii) {
ray[ii]->recursiveRayTrace(); // <-- very heavy task
});
程序突然跑了3倍。
我确信所有这些都有更深层次的解释,但这是我通过反复试验找到的。