Custom Kernel GpuMat with float
c++, cuda, gpu, opencv
Solution
You are treating image `step` as if it is a `float` offset. It is a byte offset from one row to the next.
Try something like this instead:
const float* rowsrcptr= (const float *)(((char *)srcptr)+rowInd*srcstep);
float* rowdstPtr= (float *) (((char *)dstptr)+rowInd*dststep);
from the documentation:
step – Number of bytes each matrix row occupies.
It's also a good idea to add proper cuda error checking to your code (e.g. to `func`). And you can run your code with `cuda-memcheck` to see the actual kernel failure generating the invalid reads/writes.
Problem
I'm trying to write a custom kernel using `GpuMat` data to find the arc cosine of an image's pixels. I can upload, download, and change values when I upload data when the GPU has `CV_8UC1` data but chars cannot be used to calculate arc cosines. However, when I try to convert my GPU to `CV_32FC1` type (floats) I get an illegal memory access error during the download part. Here is my code: ``` //.cu code #include <cuda_runtime.h> #include <stdlib.h> #include <iostream> #include <stdio.h> __global__ void funcKernel(const float* srcptr, float* dstptr, size_t srcstep, const size_t dststep, int cols, int rows){ int rowInd = blockIdx.y*blockDim.y+threadIdx.y; int colInd = blockIdx.x*blockDim.x+threadIdx.x; if(rowInd >= rows || colInd >= cols) return; const float* rowsrcptr=srcptr+rowInd*srcstep; float* rowdstPtr= dstptr+rowInd*dststep; float val = rowsrcptr[colInd]; if((int) val % 90 == 0) rowdstPtr[colInd] = -1 ; else{ float acos_val = acos(val); rowdstPtr[colInd] = acos_val; } } int divUp(int a, int b){ return (a+b-1)/b; } extern "C" { void func(const float* srcptr, float* dstptr, size_t srcstep, const size_t dststep, int cols, int rows){ dim3 blDim(32,8); dim3 grDim(divUp(cols, blDim.x), divUp(rows,blDim.y)); std::cout << "calling kernel from func\n"; funcKernel<<<grDim,blDim>>>(srcptr,dstptr,srcstep,dststep,cols,rows); std::cout << "done with kernel call\n"; cudaDeviceSynchronize(); } //.cpp code void callKernel(const GpuMat &src, GpuMat &dst){ float* p = (float*)src.data; float* p2 =(float*) dst.data; func(p,p2,src.step,dst.step,src.cols,src.rows); } int main(){ Mat input = imread("cat.jpg",0); Mat float_input; input.convertTo(float_input,CV_32FC1); GpuMat d_frame,d_output; Size size = float_input.size(); d_frame.upload(float_input); d_output.create(size,CV_32FC1); callKernel(d_frame,d_output); Mat output(d_output); return 0; } ``` When I run the program my compiler tells me this: OpenCV Error: Gpu API call (an illegal memory access was encountered) in copy, file /home/mobile/opencv-2.4.9/modules/dynamicuda/include/opencv2/dynamicuda/dynamicuda.hpp, line 882 terminate called after throwing an instance of 'cv::Exception' what(): /home/mobile/opencv-2.4.9/modules/dynamicuda/include/opencv2/dynamicuda/dynamicuda.hpp:882: error: (-217) an illegal memory access was encountered in function copy