使用Concurrency :: parallel_for()获得边际性能增益

时间:2012-09-26 17:30:24

标签: c++ parallel-processing

在我的应用程序中,我有一个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实现)?

2 个答案:

答案 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倍。

我确信所有这些都有更深层次的解释,但这是我通过反复试验找到的。