0

cudaを使用して簡単な画像処理を実装し始めましたが、コードにエラーがあり、デバイスからホストにピクセルをコピーするとエラーが発生します

これは私の試みです

#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <stdio.h> 
using namespace cv;

unsigned char *h_pixels;
unsigned char *d_pixels;
int bufferSize;
int width,height;

const int BLOCK_SIZE = 32;
Mat image;

void get_pixels(const char* fileName)
{
    image = imread(fileName);
    bufferSize = image.size().width * image.size().height * 3 * sizeof(unsigned char);
    width = image.size().width;
    height = image.size().height;
    h_pixels = new unsigned char[bufferSize];
    memcpy(h_pixels,image.data,bufferSize);
}

__global__ void invert_image(unsigned char* pixels,int width,int height)
{
    int row = blockIdx.y * BLOCK_SIZE + threadIdx.y;
    int col = blockIdx.x * BLOCK_SIZE + threadIdx.x;
    int cidx = (row  * width + col) * 3;
    pixels[cidx] = 255 - pixels[cidx]; 
    pixels[cidx + 1] = 255 - pixels[cidx + 1]; 
    pixels[cidx + 2] = 255 - pixels[cidx + 2]; 

}
int main()
{
    get_pixels("D:\\photos\\z.jpg");

    cudaError_t err = cudaMalloc((void**)&d_pixels,bufferSize);
    err =  cudaMemcpy(d_pixels,h_pixels,bufferSize,cudaMemcpyHostToDevice);
    dim3 dimBlock(BLOCK_SIZE,BLOCK_SIZE);
    dim3 dimGrid(width/dimBlock.x,height/dimBlock.y);

    invert_image<<<dimBlock,dimGrid>>>(d_pixels,width,height);

    unsigned char *pixels = new unsigned char[bufferSize];


    err= cudaMemcpy(pixels,d_pixels,bufferSize,cudaMemcpyDeviceToHost);// unknown error 
    const char * errStr = cudaGetErrorString(err);
    cudaFree(d_pixels);
    image.data = pixels;
    namedWindow("display image");
    imshow("display image",image);
    waitKey();
    return 0;
}

また、どうすればcudaデバイスで発生するエラーを見つけることができますか?

4

3 に答える 3

2
  • まず、画像ファイルが正しく読み取られていることを確認してください。
  • デバイスメモリがCUDA_SAFE_CALL(cudaMalloc(..))で割り当てられているかどうかを確認します
  • 画像のサイズを確認してください。画像の寸法がBLOCKSIZEの倍数でない場合は、一部のインデックスが欠落している可能性があり、画像が完全に反転されていません。
  • カーネル呼び出しの後にcudaDeviceSynchronizeを呼び出し、その戻り値を確認します。
  • とにかくカーネルを呼び出さずにコードを実行すると、エラーが発生しますか?
  • h_pixelsを解放しておらず、メモリリークが発生している可能性があります。
  • カーネルでBLOCKSIZEを使用する代わりに、「blockDim.x」を使用することもできます。したがって、「blockIdx.x * blockDim.x+threadIdx.x」のようなインデックスを計算します
  • カーネルコードのメモリ領域に触れないようにしてください。つまり、カーネルでのメモリの更新(ピクセル配列にアクセスする行)をコメントアウトして、プログラムが引き続き失敗するかどうかを確認します。それが失敗し続けない場合は、範囲外にアクセスしている可能性があります。
于 2012-09-18T20:49:25.803 に答える
2

OpenCV イメージは連続していません。各行は 4 バイトまたは 8 バイトにアラインされています。また、正しくstep計算できるように、Matのフィールドを CUDA カーネルに渡す必要があります。cidx出力インデックスを計算するための一般的な式は次のとおりです。

cidx = row * (step/elementSize) + (NumberOfChannels * col);

あなたの場合、それは次のようになります。

cidx = row * step + (3 * col);

画像の配置を参照すると、バッファサイズは に等しくなりimage.step * image.size().heightます。

次は、3 番目のポイントで @phoad によって指摘されたものです。画像全体をカバーするのに十分な数のスレッド ブロックを作成する必要があります。

これは、任意の画像サイズに対して十分な数のブロックを作成するグリッドの一般的な式です。

dim3 block(BLOCK_SIZE,BLOCK_SIZE);

dim3 grid((width + block.x - 1)/block.x,(height + block.y - 1)/block.y);

于 2012-09-19T05:01:45.590 に答える
1

カーネル呼び出しの直後に次のコマンドを使用して、カーネル エラーを出力します。

printf("error code: %s\n",cudaGetErrorString(cudaGetLastError()))
于 2012-09-19T11:04:55.487 に答える