0

編集:私の最初のコードサンプルは間違っていました。よりシンプルに修正されました。

大きなベクトルと行列の間の代数演算用にC++ライブラリを実装します。x86-x64 CPUで、OpenMP並列ベクトルの追加、ドット積などがシングルスレッドよりも高速ではないことがわかりました。並列操作は、シングルスレッドよりも-1%〜6%高速です。これは、メモリ帯域幅の制限が原因で発生します(私は思います)。

したがって、問題は、次のようなコードに実際のパフォーマンス上の利点があるかどうかです。

void DenseMatrix::identity()
{
    assert(height == width);
    size_t i = 0;
    #pragma omp parallel for if (height > OPENMP_BREAK2)
    for(unsigned int y = 0; y < height; y++)
        for(unsigned int x = 0; x < width; x++, i++)
            elements[i] = x == y ? 1 : 0;
}

このサンプルでは、​​OpenMPを使用することによる重大な欠点はありません。しかし、スパースベクトルとスパース行列を使用してOpenMPで作業している場合、たとえば* .push_back()を使用することはできません。その場合、質問は深刻になります。(スパースベクトルの要素はデンスベクトルのように連続的ではないため、並列プログラミングには欠点があります。これは、結果要素がいつでも到着する可能性があるためです。インデックスが低いものから高いものへの変換ではありません)

4

1 に答える 1

1

これはメモリ帯域幅の問題ではないと思います。r:rは複数のスレッドからアクセスされるため、データ競合と共有の誤りの両方が発生ます。偽の共有は、パフォーマンスを劇的に低下させる可能性があります。

でデータ競合が発生しているため、正しい答えさえ得られるかどうか疑問に思っていますr。正しい答えが得られましたか?

ただし、解決策は非常に簡単です。実行される操作rリダクションreductionであり、OpenMP の句によって簡単に実現できます。

reduction(+ : r)の後に単純に追加してみてください#pragma omp parallel

(注: の加算doubleは交換可能でも結合的でもありません。精度エラーや、シリアル コードの結果との違いが見られる場合があります。)

于 2013-03-19T17:49:19.863 に答える