0
votes

I have build a project in Visual Studio 2010 that uses a mexfunction and a wrapper function that calls a kernel function in Cuda. My problem is that when I am trying to read the data I have passed to the wrapper function the programs crashes. I paste some of my code bellow and I put some notes in the exact place where the problem occurs.

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    // input validation
    if (nrhs != 2 || nlhs > 1) {
        mexErrMsgTxt("Wrong number of input/output arguments.");
    }
    if (!mxIsSingle(prhs[0]) || !mxIsSingle(prhs[1])) {
        mexErrMsgTxt("Inputs must be single arrays.");
    }
    if (mxIsComplex(prhs[0]) || mxIsComplex(prhs[1])) {
        mexErrMsgTxt("Inputs must be real arrays.");
    }
    if (mxIsSparse(prhs[0]) || mxIsSparse(prhs[1])) {
        mexErrMsgTxt("Inputs must be dense arrays.");
    }
    if (mxGetNumberOfElements(prhs[0]) != mxGetNumberOfElements(prhs[1])) {
        mexErrMsgTxt("Inputs must have the same size.");
    }

    // create ouput array
    mwSize numel = mxGetNumberOfElements(prhs[0]);
    mwSize ndims = mxGetNumberOfDimensions(prhs[0]);
    const mwSize *dims = mxGetDimensions(prhs[0]);
    int rows = mxGetM(prhs[0]); /* Get the dimensions of A */
    int cols = mxGetN(prhs[0]);
    //plhs[0] = mxCreateNumericArray(1, dims, mxSINGLE_CLASS, mxREAL);
    //plhs[0] = mxCreateDoubleMatrix(rows,1,mxREAL);
    // Create a rows-by-3 real float
    plhs[0] = mxCreateNumericMatrix(rows, 1, mxSINGLE_CLASS, mxREAL);

    // get pointers to data
    float *h_c = (float*) mxGetData(plhs[0]);
    float *h_a = (float*) mxGetData(prhs[0]);
    float *h_b = (float*) mxGetData(prhs[1]);

    myGPU::cudaFunction_wrapper(h_a, h_b, h_c, rows, cols);  

In the .cu file the following code exists.

namespace myGPU
{//begin namespace

extern "C++" void cudaFunction_wrapper( float* h_A, float* h_B, float* h_C, int rows, int cols );

__global__ void cudaFunction( float* A, float* B, float* C, int rows, int cols )
{
    int j = blockDim.x * blockIdx.x + threadIdx.x;
    int i = blockDim.y * blockIdx.y + threadIdx.y;

    int m,n;
    for(m = 0; m < rows; m++)
        for(n = 0; n < cols; n++)
             C[m] = A[m + rows*n];
}

void cudaFunction_wrapper( float* h_A, float* h_B, float* h_C, int rows, int cols )
{

     // Error code to check return values for CUDA calls
    cudaError_t err = cudaSuccess;
    int numElements =  rows * cols;
    size_t size = numElements * sizeof(float);

    // Allocate the device input matrix B
    float *d_A = NULL;
    err = cudaMalloc((void **)&d_A, size);
    if (err != cudaSuccess)
    {
        fprintf(stderr, "Failed to allocate device vector A (error code %s)!\n", cudaGetErrorString(err));
        exit(EXIT_FAILURE);
    }

    // Allocate the device input matrix B
    float *d_B = NULL;
    err = cudaMalloc((void **)&d_B, size);

    if (err != cudaSuccess)
    {
        fprintf(stderr, "Failed to allocate device vector B (error code %s)!\n", cudaGetErrorString(err));
        exit(EXIT_FAILURE);
    }

    // Allocate the device output matrix C
    float *d_C = NULL;

    //the returnen value is a vector
    err = cudaMalloc((void **)&d_C, rows * sizeof(float) );

    if (err != cudaSuccess)
    {
        fprintf(stderr, "Failed to allocate device vector C (error code %s)!\n", cudaGetErrorString(err));
        exit(EXIT_FAILURE);
    }

    printf("Copy input data from the host memory to the CUDA device\n");
    err = cudaMemcpy(d_A, h_A, size, cudaMemcpyHostToDevice);

    if (err != cudaSuccess)
    {
        fprintf(stderr, "Failed to copy vector A from host to device (error code %s)!\n", cudaGetErrorString(err));
        exit(EXIT_FAILURE);
    }

    err = cudaMemcpy(d_B, h_B, size, cudaMemcpyHostToDevice);

    if (err != cudaSuccess)
    {
        fprintf(stderr, "Failed to copy vector B from host to device (error code %s)!\n", cudaGetErrorString(err));
        exit(EXIT_FAILURE);
    }

    // Launch the Vector Add CUDA Kernel
    int threadsPerBlock = 256;
    int blocksPerGrid =(numElements + threadsPerBlock - 1) / threadsPerBlock;

    printf("CUDA kernel launch with %d blocks of %d threads\n", blocksPerGrid, threadsPerBlock);

   /* 
    /////////////////////////////////////////////////////
    ///////////// Works WHEN ACCESS h_A /////////////////
    /////////////////////////////////////////////////////

    int m,n;
    for(m = 0; m < rows; m++)
        for(n = 0; n < cols; n++)
             mexPrintf("%f \n", h_A[m + rows*n]) ;

    /////////////////////////////////////////////////////
    ///////////// IT CRASHES HERE WHEN ACCESS d_B ///////
    /////////////////////////////////////////////////////
        for(m = 0; m < rows; m++)
        for(n = 0; n < cols; n++)
             mexPrintf("%f \n", d_B[m + rows*n]) ;

    */

    cudaFunction<<<blocksPerGrid, threadsPerBlock>>>( d_A, d_B, d_C, rows, cols );


    err = cudaGetLastError();

    if (err != cudaSuccess)
    {
        fprintf(stderr, "Failed to launch vectorAdd kernel (error code %s)!\n", cudaGetErrorString(err));
        exit(EXIT_FAILURE);
    }


    // Copy the device result vector in device memory to the host result vector
    // in host memory.
    printf("Copy output data from the CUDA device to the host memory\n");
    err = cudaMemcpy(h_C, d_C, rows * sizeof(float) , cudaMemcpyDeviceToHost);

    if (err != cudaSuccess)
    {
        fprintf(stderr, "Failed to copy vector C from device to host (error code %s)!\n", cudaGetErrorString(err));
        exit(EXIT_FAILURE);
    }


    // Free device global memory
    err = cudaFree(d_A);

    if (err != cudaSuccess)
    {
        fprintf(stderr, "Failed to free device vector A (error code %s)!\n", cudaGetErrorString(err));
        exit(EXIT_FAILURE);
    }
    err = cudaFree(d_B);

    if (err != cudaSuccess)
    {
        fprintf(stderr, "Failed to free device vector B (error code %s)!\n", cudaGetErrorString(err));
        exit(EXIT_FAILURE);
    }

    err = cudaFree(d_C);

    if (err != cudaSuccess)
    {
        fprintf(stderr, "Failed to free device vector C (error code %s)!\n", cudaGetErrorString(err));
        exit(EXIT_FAILURE);
    }

    // Reset the device and exit
    err = cudaDeviceReset();

    if (err != cudaSuccess)
    {
        fprintf(stderr, "Failed to deinitialize the device! error=%s\n", cudaGetErrorString(err));
        exit(EXIT_FAILURE);
    }


}


}//end namespace 

Also a second question I would like to ask is how can we debug a process in VS with Nsight by attaching. I followed the explanation in http://http.developer.nvidia.com/NsightVisualStudio/2.2/Documentation/UserGuide/HTML/Content/Attach_CUDA_to_Process.htm but the attach button can not be enabled. By the way Matlab is the program that I would like to attach.

Thank you in advance.

PS: Win 7 84x, CUDA SDK 5.5, Visual Studio 2010, Matlab 2011a

1
Don't you want this plhs[0] = mxCreateNumericMatrix(rows, 1, mxSINGLE_CLASS, mxREAL); to be plhs[0] = mxCreateNumericMatrix(rows, cols, mxSINGLE_CLASS, mxREAL);? - Praetorian
That is because the output is a vector and that is why I am using err = cudaMalloc((void **)&d_C, rows); - Darkmoor
OK, but within cudaFunction you're iterating over that memory as if it were a matrix C[m + rows*n] = A[m + rows*n];. C doesn't have enough memory allocated, and you're overrunning the bounds. And what is this supposed to be cudaFunctio<<<blocksPerGrid, threadsPerBlock>>>(...);? - Praetorian
@Praetorian: This is cudaFunction( float* A, float* B, float* C, int rows, int cols ), spelling mistake. I think the problem is on allocating memory. Because it crashes in d_B, before entering kernel(comments). - Darkmoor
Have you seen the solution for Nsight+MATLAB here: stackoverflow.com/questions/11732840/… - chappjc

1 Answers

2
votes

For d_C, shouldn't you use cudaMalloc((void **)&d_C, rows*sizeof(float)); instead of cudaMalloc((void **)&d_C, rows);?

Regarding the crash on mexPrintf("%f \n", d_B[m + rows*n]), wouldn't the fact that d_B is device (GPU) memory be a problem here?

Also, what Praetorian said about plhs[0] creation being too small for the required buffer of h_c.