1

float の配列で最大要素を見つける関数の 2 つのバージョンを実装しようとしています。ただし、私の並列関数は、シリアル コードよりもはるかに遅く実行されているように見えました。

4194304 (2048 * 2048) float の配列を使用すると、次の数値 (マイクロ秒単位) が得られます。

  • シリアルコード:9433

  • PPL コード: 24184 ( 2 倍以上遅い)

  • OpenMP コード: 862093 (ほぼ100倍遅い)

コードは次のとおりです。

PPL:

float find_largest_element_in_matrix_PPL(float* m, size_t dims)
{
    float max_element;
    int row, col;
    concurrency::combinable<float> locals([] { return (float)INT_MIN; });
    concurrency::parallel_for(size_t(0), dims * dims, [&locals](int curr)
    {
        float &localMax = locals.local();
        localMax = max<float>(localMax, curr);
    });

    max_element = locals.combine([](float left, float right) { return max<float>(left, right); });
    return max_element;
}

OpenMP:

float find_largest_element_in_matrix_OMP(float* m, unsigned const int dims)
{
    float max_value = 0.0;
    int i, row, col, index;

    #pragma omp parallel for private(i) shared(max_value, index)
    for (i = 0; i < dims * dims; ++i)
    {
#pragma omp critical
        if (m[i] > max_value)
        {
            max_value = m[i];
            index = i;
        }
    }

    //row = index / dims;
    //col = index % dims;
    return max_value;
}

  1. コードの実行速度が遅い原因は何ですか? 何か不足していますか?

  2. 私が間違っていることを見つけるのを手伝ってもらえますか?

4

1 に答える 1

1

そのため、Baum mit Augenが気付いたように、OpenMP の問題は、クリティカル セクションがあり、コードが実際には並列ではなく同期的に実行されることでした。クリティカルセクションを削除するとうまくいきました。

PPL については、OpenMP よりも多くの準備 (スレッドなどの作成) を行うことがわかったので、速度が低下しました。


アップデート

したがって、OpenMP で max 要素を見つけるための正しいバリアントは次のとおりです (クリティカル セクションは引き続き必要ですが、ifブロック内にあります)。

float find_largest_element_in_matrix_OMP(float* m, unsigned const int dims)
{
    float max_value = 0.0;
    int i, row, col, index;

    #pragma omp parallel for
    for (i = 0; i < dims * dims; ++i)
    {
        if (m[i] > max_value)
        {
            #pragma omp critical
            max_value = m[i];
        }
    }
    return max_value;
}

PS: テストされていません。

于 2015-12-19T18:45:13.440 に答える