1

私のアプリケーションでは、次のように、約 1,000 万個のアイテムを実行する 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 に答える