我是 CUDA 的新手,我正在尝试用它做我的第一个项目。我正在尝试将图像数据推送到 GPU,在那里将其设为黑白并将其写入新图像。但是程序给了我一个黑色图像而不是黑白版本。我究竟做错了什么?图像的宽度和高度为 3840x2160。
__global__ void addMatrix(unsigned char *DataOut, unsigned char *DataIn)
{
int idx = threadIdx.x;
DataOut[idx] = (DataIn[idx] + DataIn[idx + 1] + DataIn[idx + 2]) / 3;
//
}
int main()
{
int iWidth, iHeight, iBpp, iHeightOut, iWidthOut;
vector<unsigned char> pDataIn;
vector<unsigned char> pDataOut;
int error1 = LoadBmpFile(L"3840x2160.bmp", iWidth, iHeight, iBpp, pDataIn);
if (error1 != 0 || pDataIn.size() == 0 || iBpp != 32)
{
std::cout << "erroror load input file!\n";
}
pDataOut.resize(pDataIn.size()/4);
unsigned int SizeIn, SizeOut;
unsigned char *devDatOut, *devDatIn, *PInData, *POutData;
int i = 0;
SizeIn = pDataIn.size();
SizeOut = pDataOut.size();
PInData = pDataIn.data();
POutData = pDataOut.data();
i = cudaMalloc((void**)&devDatIn, SizeIn * sizeof(unsigned char));
if(i != 0)
{
printf("cudaMalloc __e FAIL! Code: %d\n", i);
_getch();
}
i = cudaMalloc((void**)&devDatOut, SizeOut * sizeof(unsigned char));
if(i != cudaSuccess)
printf("cudaMalloc __e FAIL! Code: %d\n", i);
i = cudaMemcpy(devDatIn, PInData, SizeIn * sizeof(unsigned char), cudaMemcpyHostToDevice);
if(i != cudaSuccess)
printf(" cudaMemcpy __e FAIL! Code: %d\n", i);
i = cudaMemcpy(devDatOut, POutData, SizeOut * sizeof(unsigned char), cudaMemcpyHostToDevice);
if(i != cudaSuccess)
printf(" cudaMemcpy __e FAIL! Code: %d\n", i);
dim3 gridSize = dim3(1, 1, 1);
dim3 blockSize = dim3(SizeIn, 1, 1);
addMatrix<<<gridSize, blockSize>>>(devDatIn, devDatOut);
if ( i == cudaGetLastError() )
{
printf( "Error! %d\n", cudaGetLastError() );
_getch;
}
cudaEvent_t syncEvent;
cudaEventCreate(&syncEvent);
cudaEventRecord(syncEvent, 0);
cudaEventSynchronize(syncEvent);
cudaMemcpy(POutData, devDatOut, SizeOut * sizeof(unsigned char), cudaMemcpyDeviceToHost);
cudaEventDestroy(syncEvent);
i = WriteBmpFile(L"3840x2160_test2.bmp", iWidth, iHeight, 8, pDataOut.size(), pDataOut.data(), false);
if(i != 0)
printf(" cudaMemcpy __e FAIL! Code: %d\n", i);
cudaFree(devDatOut);
cudaFree(devDatIn);
}
编辑 1:
最佳答案
正如在评论中看到的那样,您在每个 block 中启动了太多线程并且启动可能会失败,但是您的错误检查不完整并且您看不到它。 参见 this answer用于在启动内核后进行适当的错误检查。
顺便说一句,您必须启动几个线程较少的 block ,而不是一个包含所有这些线程的 block 。 例如,它可能是 2000 个 block ,每个 block 包含 1024 个线程。在我目前的卡片上,1024 个线程是我在每个 block 中可以拥有的最大值,因此如果我需要更多线程,我会启动多个 block ,并且通常我会启动更多 block 和更少的线程以获得更好的占用率。 您可以了解更多入住情况with this presentation .
例如,如果您总共有 10,000 个像素,则可以启动 20 个 block ,每个 block 有 500 个线程。 您可以在一个维度上为两者执行此操作:
dim3 blocks(20, 1, 1);
dim3 threads(500, 1, 1);
myKernel<<<blocks, threads>>>(...);
您的内核需要进行一些更改才能将每个特定 block 中的线程索引正确映射到内存中图片缓冲区中的唯一线性索引(在浏览器中编写,未针对您的特定项目进行测试,但线性化用一支好的旧钢笔在纸上思考就很容易理解):
__global__ void addMatrix(unsigned char *DataOut, unsigned char *DataIn)
{
int idx = BlockIdx.x * BlockDim.x + threadIdx.x;
unsigned char average = (unsigned char)((DataIn[idx] + DataIn[idx + 1] + DataIn[idx + 2]) / 3);
DataOut[idx + 0] = average;
DataOut[idx + 1] = average;
DataOut[idx + 2] = average;
}
关于c++ - CUDA中图像处理的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36597281/