0

float* メモリ ブロックのコードでいくつかの計算を行います。私は画像に取り組んでいるので、幅 * 高さのポイントと 180 回転でこれを行う必要があります。これはコード内で唯一の並列化可能な手順であるため、180 スレッド (1 度の回転ごとに 1 つ) を開始しています。画像を回転させ、回転ごとに、すべての点について結果の float 値を取得します。各ポイントで現在の最大値を格納する別の float* ブロックがあります。

if(resultMap[i] < convrst)
{
    resultMap[i] = convrst;
    rMap[i] = (unsigned char)r0;
    oMap[i] = (unsigned char)index;
}

resultMap には現在の最高値が格納されます。convrst は畳み込みの結果であり、現在の結果が前の結果よりも大きい場合は、値に加えて、その時点での半径 (r0) と回転 (インデックス) が保存されます。r0 はもともと int であり、インデックスでもあります。i は 0 から imgsize-1 までのカウンターです

{ } 部分に代入がなければ、コード全体は 2 秒程度で終了し、代入には 50 秒かかります (これは、そのコードで同期の問題を回避するためにロックを省略したことを考慮していません)。

そのコードはなぜこんなに遅いのでしょうか? 速く終了させるにはどうすればよいでしょうか?

4

1 に答える 1

2

カーネルに書き込みを含めると速度が大幅に低下する理由は、この質問と同じです (OpenCL に関するものですが、原則は同じです)。NVIDIA コンパイラは、「デッド」コード、つまり共有メモリまたはグローバル メモリ書き込みに寄与しないコードを最適化することに非常に積極的です。したがって、質問に示されているように、グローバルメモリへの書き込みを含めない場合、コンパイラは大量のカーネルを最適化して実行時間を大幅に短縮していると思います。

したがって、私がリンクした他の質問のように、本当の問題は、なぜカーネルが終了するのに 50 秒かかるのかということです。それには、コードとそれを呼び出す実行パラメーターに関する詳細情報が必要になりますが、あなたが書いたように、180 スレッドしか実行していない場合、それが原因である可能性があります。GPU は、ピーク パフォーマンスのようなものを達成するために、それよりもはるかに多くの並列処理を必要とします。

于 2012-05-14T16:10:01.670 に答える