MEMS
MEMS

Reputation: 647

OpenCl clEnqueueMapBuffer doesn't work properly?

As far as I know you can use clEnqueueMapBuffer for accessing memory objects. Instead of using the read/write operations you can map a memory object on a device to a memory region on the host. I wrote a very simple code to test it. this code sends charter 'X' to GPU and the kernel adds 1 to it so we should get 'Y' but I don't. it seems that clEnqueueUnmapMemObject doesn't copy the result that is stored in the GPU memory to the buffer on the host! this is my code:

#include <iostream>
#include <CL\cl.h>
using namespace std;
#pragma warning(disable : 4996)
#define PROGRAM "__kernel void hello(__global char* string )\
{\
string[0] = string[0] + 1;\
}"

int main() {
cl_platform_id platform; cl_device_id device; cl_context context;
cl_program program; cl_int error; cl_build_status status;

char *programBuffer = PROGRAM;   

// make contex
clGetPlatformIDs(1, &platform, NULL);
clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &device, NULL);
context = clCreateContext(NULL, 1, &device, NULL, NULL, NULL);

//built program
program = clCreateProgramWithSource(context, 1, (const char**)&programBuffer, nullptr, NULL);
const char options[] = "-cl-std=CL1.1 -cl-mad-enable -Werror";
error = clBuildProgram(program, 1, &device, options, NULL, NULL);

// create kernel 
cl_command_queue   command_queue;
command_queue = clCreateCommandQueue(context, device, NULL, nullptr);
cl_kernel kernels, found_kernel;
cl_uint num_kernels;

error = clCreateKernelsInProgram(program, 0, nullptr, &num_kernels);
kernels = clCreateKernel(program, "hello", nullptr);
//make buffers
cl_mem memobj = clCreateBuffer(context, CL_MEM_ALLOC_HOST_PTR| CL_MEM_READ_WRITE, 2 * sizeof(char), nullptr, &error);//if nulptr nazarim then itt will retun null pointer
error = clSetKernelArg(kernels, 0, sizeof(cl_mem), (void *)&memobj);
// I am goign to send this data to GPU
char *CPU_2_GPU_Data = new char[2]{ "X" };
void* mapbuffer =clEnqueueMapBuffer(command_queue, memobj, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, 2 * sizeof(char), 0, nullptr, nullptr, &error);
memccpy(mapbuffer, CPU_2_GPU_Data, 0, 2 * sizeof(char));
cout<<"I am sending this dat to GPU:"<<(char*)(mapbuffer)<<endl;
error = clEnqueueTask(command_queue, kernels, 0, nullptr, nullptr);
clEnqueueUnmapMemObject(command_queue, memobj, mapbuffer, 1, nullptr, nullptr);
cout << "I am getiing this data from GPU:" << (char*)(mapbuffer) << endl;
clReleaseContext(context);
return 0;

}

actually I can send data to the GPU using Mapping memory objects but I cant read the result. to make the code work I have to explicitly ask the GPU to send me the data as:

char* newbuffer = new char[2];
clEnqueueReadBuffer(command_queue, memobj, CL_TRUE, 0, 2 * sizeof(char), newbuffer, 0, nullptr, nullptr);
cout << "the result is :" << newbuffer << endl;

why that happens?? why I can send data to GPU using Mapping memory objects but I cant get the result back?

Upvotes: 0

Views: 727

Answers (1)

Lee
Lee

Reputation: 930

The intent is that: 1) You map to read it on the host. 2) You then unmap it so the GPU can use it again. 3) You then map it again to read it from the host. 4) Then unmap it to clean up.

You seem to be mapping, launching a task and then unmapping. So at the point where you try to read the data the host actually can't read it any more because you just unmapped it!

Upvotes: 2

Related Questions