Results 1 to 10 of 10

Thread: Using clEnqueueWriteBuffer with c++ vectors

Hybrid View

  1. #1
    Newbie
    Join Date
    Nov 2013
    Posts
    4

    Using clEnqueueWriteBuffer with c++ vectors

    Hello all,

    I am a novice to programming in general and am attempting to add two 2D c++ vectors a specified amount of times on the GPU using OpenCL. I think I am running into issues when I attempt to write my data to the created device buffer. I am uncertain as to how I need to create my vectors in order to pass them to GPU. When running this code, I get a pointer error when I attempt to access the data that is contained within the vector that receives the data from the GPU indicating to me that the data are never actually brought back from the device.

    Here I post a portion of my code. I have some functions that I wrote called packVector and unPackVector. These are simply used to make the vectors one dimensional so I can pass them to the GPU and when receiving 1D data from the GPU, make it 2D.

    I have successfully implemented this code with 2D arrays but I am getting memory leaks and therefore would like to use vectors.

    The GPU I am using is a NVIDIA GeForce 9400M and I am using the OpenCL framework via Mac OS X 10.7.5

    Thank you in advance.

    Code :
            int n1 = 2;
            int n2 = 2;
    	int dims = n1*n2;
    	int iters = 2;
     
    	std::vector<std::vector<float> > h_xx(n1, std::vector<float>(n2));
    	std::vector<std::vector<float> > h_yy(n1, std::vector<float>(n2));
    	std::vector<std::vector<float> > h_zz(n1, std::vector<float>(n2));
     
    	std::vector<float> h_x(dims);
    	std::vector<float> h_y(dims);
    	std::vector<float> h_z(dims);
     
     
    	for (int i = 0; i < n1; ++i){
    		for (int j = 0; j < n2; ++j){
    			h_xx[i][j] = 1;
    			h_yy[i][j] = 1;
    		}
    	}
     
     
    	cl_mem d_xx, d_yy, d_zz;
     
        d_xx = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(float)*dims, NULL, &err);
        if(err != CL_SUCCESS){
            std::cout << "Error: Could not create the buffer." << std::endl;
            exit(1);
        }
     
        d_yy = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(float)*dims, NULL, &err);
        if(err != CL_SUCCESS){
            std::cout << "Error: Could not create the buffer." << std::endl;
            exit(1);
        }
     
        d_zz = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(float)*dims, NULL, &err);
        if(err != CL_SUCCESS){
            std::cout << "Error: Could not create the buffer." << std::endl;
            exit(1);
        }
     
        arr.packVector(h_xx, h_x);
        arr.packVector(h_yy, h_y);
     
        clEnqueueWriteBuffer(queue, d_xx, CL_FALSE, 0, sizeof(float)*h_x.size(), &h_x, 0, NULL, NULL);
        if(err != CL_SUCCESS){
            std::cout << "Error: Could not write vector to buffer." << std::endl;
            std::cout << "OpenCL error code: " << std::endl;
            exit(1);
        }
     
        clEnqueueWriteBuffer(queue, d_yy, CL_FALSE, 0, sizeof(float)*h_y.size(), &h_y, 0, NULL, NULL);
        if(err != CL_SUCCESS){
            std::cout << "Error: Could not write vector to buffer." << std::endl;
            std::cout << "OpenCL error code: " << std::endl;
            exit(1);
        }
     
     
        err = clSetKernelArg(kernel, 0, sizeof(cl_mem), &d_xx);
        if(err != CL_SUCCESS){
            std::cout << "Error: Could not set the kernel argument." << std::endl;
    		std::cout << "OpenCL error code: " << err << std::endl;
            exit(1);
        }
        err = clSetKernelArg(kernel, 1, sizeof(cl_mem), &d_yy);
        if(err != CL_SUCCESS){
            std::cout << "Error: Could not set the kernel argument." << std::endl;
    		std::cout << "OpenCL error code: " << err << std::endl;
            exit(1);
        }
        err = clSetKernelArg(kernel, 2, sizeof(cl_mem), &d_zz);
        if(err != CL_SUCCESS){
            std::cout << "Error: Could not set the kernel argument." << std::endl;
    		std::cout << "OpenCL error code: " << err << std::endl;
            exit(1);
        }
     
        err = clSetKernelArg(kernel, 3, sizeof(iters), &iters);
        if(err != CL_SUCCESS){
            std::cout << "Error: Could not set the integer kernel argument." << std::endl;
            std::cout << "OpenCL error code: " << err << std::endl;
            exit(1);
        }
     
        size_t work_units_per_kernel = dims;
        err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &work_units_per_kernel, NULL, 0, NULL, NULL);
        if(err != CL_SUCCESS){
            std::cout << "Error: Could not execute the kernel." << std::endl;
            exit(1);
        }
     
        err = clEnqueueReadBuffer(queue, d_zz, CL_TRUE, 0, sizeof(float)*h_z.size(), &h_z, 0, NULL, NULL);
        if(err != CL_SUCCESS){
            std::cout << "Error: Could not read vector from the kernel." << std::endl;
            std::cout << "OpenCL error code: " << std::endl;
            exit(1);
        }
     
       arr.unPackVector(h_z, h_zz);
     
        arr.printVec2D(h_zz);

  2. #2
    Senior Member
    Join Date
    Oct 2012
    Posts
    166
    are you shure that the reference to the std::vector will give you a data array of floats? this would mean that &h_x is the same as a float[dims]

  3. #3
    Newbie
    Join Date
    Nov 2013
    Posts
    4
    Quote Originally Posted by clint3112 View Post
    are you shure that the reference to the std::vector will give you a data array of floats? this would mean that &h_x is the same as a float[dims]
    Thank you clint3112 for your reply.

    No, I am not sure. I believe that is why my program does not work. How then should I pass the vector of floats to the function clEnqueueWriteBuffer?

  4. #4
    Senior Member
    Join Date
    Oct 2012
    Posts
    103
    &h_z.at(0) will give you a valid pointer on the first element of h_z.

  5. #5
    Newbie
    Join Date
    Nov 2013
    Posts
    4
    Thank you utnapishtim for your reply as well.

    Is that the only way I can reference the data within my vector as a valid pointer? I think that means that I might have to loop over all of the elements of my vector in order to get my data to the GPU. This I would rather not do as it appears that it might be rather slow versus copying an entire array. Is there any other way that I might copy the data from my vector to the device buffer?

    Thanks again for all of the help.

  6. #6
    Senior Member
    Join Date
    Oct 2012
    Posts
    166
    &h_z.at(0) is the same as float foo[n]; &foo[0]; So yiu dont need to copy anything. Just have to pass that adress to the enque call.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •