1

在我的应用程序中,我有一个运行大约一千万个项目的 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()方法是一个小方法,独立于其他节点。因此,并行执行这个 for 循环将是非常有利的。因为这只是一件小事,所以这次我想远离 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 实现)?

4

2 回答 2

1

在一个问题上投入更多的核心并不总能带来改进。事实上,在最坏的情况下,它甚至会降低性能。从使用多核中受益取决于很多事情,例如所涉及的共享数据量。有些问题本质上是可并行的,有些则不是。

于 2012-09-26T17:40:14.740 回答
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 倍的速度。

我确信这一切都有更深层次的解释,但这是我通过反复试验发现的。

于 2012-10-23T12:26:53.920 回答