-1

CUDA 関連の質問があります :)。私はCUDAの使用に比較的慣れていないので、この「パフォーマンス」が大丈夫かどうか知りたいです。

C# と Cudafy.Net を使用しています。

スクリーンショットから計算したグレースケール画像 (float[] で表される) があります (画像のサイズは 1920x1018 ピクセルです)。

ここで、GPU 上で (Cudafy.Net を介して) 実行される Sobel フィルターを使用します。これは次のようになります。

    [Cudafy]
    public static void PenaltyKernel(GThread thread, Single[] data, Single[] res, Int32 width, Int32 height)
    {
        Single[] shared_data = thread.AllocateShared<Single>("shared_data", BLOCK_WIDTH * BLOCK_WIDTH);
        ///Map from threadIdx/BlockIdx to Pixel Position
        int x = thread.threadIdx.x - FILTER_WIDTH + thread.blockIdx.x * TILE_WIDTH;
        int y = thread.threadIdx.y - FILTER_WIDTH + thread.blockIdx.y * TILE_WIDTH;
        shared_data[thread.threadIdx.x + thread.threadIdx.y * BLOCK_WIDTH] = data[x + y * width];
        thread.SyncThreads();

        if (thread.threadIdx.x >= FILTER_WIDTH && thread.threadIdx.x < (BLOCK_WIDTH - FILTER_WIDTH) &&
            thread.threadIdx.y >= FILTER_WIDTH && thread.threadIdx.y < (BLOCK_WIDTH - FILTER_WIDTH))
        {
            ///Horizontal Filtering (detects horizontal Edges)
            Single diffHorizontal = 0;
            int idx = GetIndex(thread.threadIdx.x - 1, thread.threadIdx.y - 1, BLOCK_WIDTH);
            diffHorizontal -= shared_data[idx];
            idx++;
            diffHorizontal -= 2 * shared_data[idx];
            idx++;
            diffHorizontal -= shared_data[idx];
            idx += 2*BLOCK_WIDTH;
            diffHorizontal += shared_data[idx];
            idx++;
            diffHorizontal += 2 * shared_data[idx];
            idx++;
            diffHorizontal += shared_data[idx];

            ///Vertical Filtering (detects vertical Edges)
            Single diffVertical = 0;
            idx = GetIndex(thread.threadIdx.x - 1, thread.threadIdx.y - 1, BLOCK_WIDTH);
            diffVertical -= shared_data[idx];
            idx += BLOCK_WIDTH;
            diffVertical -= 2 * shared_data[idx];
            idx += BLOCK_WIDTH;
            diffVertical -= shared_data[idx];
            idx = GetIndex(thread.threadIdx.x + 1, thread.threadIdx.y - 1, BLOCK_WIDTH);
            diffVertical += shared_data[idx];
            idx += BLOCK_WIDTH;
            diffVertical += 2 * shared_data[idx];
            idx += BLOCK_WIDTH;
            diffVertical += shared_data[idx];

            ///Convert the "edgyness" for the Pixel and cut off at 1.0
            Single diff = GMath.Min(1.0f, GMath.Sqrt(diffHorizontal * diffHorizontal + diffVertical * diffVertical));

            ///Get the Array-Index
            idx = GetIndex(x, y, width);
            ///Set the Value
            res[x + y * width] = diff;
        }
    }

ランタイム前に設定される定数値:

TILE_WIDTH = 16;
FILTER_WIDTH = 1;
BLOCK_WIDTH = TILE_WIDTH + 2 * FILTER_WIDTH;

この "PenaltyKernel" 関数を実行すると配列のメモリ割り当て、デバイスとの間でのデータのコピーが含まれ、実行時間は平均で約6.2 ミリ秒になります (GTX 680 GT を使用)。

だから私の質問は、この速度が大丈夫かどうか(それは毎秒約161フレームになります)、それとも何か足りないのですか?私のソーベルフィルターは大丈夫ですか(つまり、結果は良さそうです:))?

どんな助けでも大歓迎です!

4

1 に答える 1

0

十分な速度だと思います。多くの時間は、ホストとデバイスの間でデータをコピーするためのものです (特に、GPU から CPU への転送は低速です)。

速度に関する注意: 一般に、画像が小さい場合、GPU での画像処理は CPU での処理よりも遅くなる可能性があります (コードをテストしていないため、これがあなたの場合に当てはまるかどうかはわかりません)。ただし、イメージが大きいほど、ホストで処理するよりもデバイスで処理する方が速くなります。

于 2013-06-16T20:02:41.623 に答える