2017-10-05 5 views
-1

이전에 CUDA로 작성된 코드를 OpenCL을 사용하여 구현하여 Altera FPGA에서 실행하려고합니다. 버퍼에 있어야하는 데이터를 다시 읽는 데 문제가 있습니다. CUDA 버전과 동일한 구조를 사용합니다. 다른 점은 cudaMalloc이 모든 유형의 포인터에 대해 메모리를 할당 할 수있는 반면 clCreateBuffer는 cl_mem을 사용해야한다는 것입니다. 내 코드는 다음과 같습니다OpenCL, 호스트에서 장치 버퍼 포인터를 관리합니까?

cl_mem d_buffer=clCreateBuffer(...); 
//CUDA version: 
//float* d_buffer; 
//cudaMalloc((void **)&d_buffer, MemSz); 

clEnqueueWriteBuffer(queue, d_buffer, ..., h_data,); 
//cudaMemcpy(d_buffer, h_Data, MemSz, cudaMemcpyHostToDevice); 

#define d_buffer(index1, index2, index3) &d_buffer + index1/index2*index3 
//#define d_buffer(index1, index2, index3) d_buffer + index1/index2*index3 

cl_mem* d_data=d_buffer(1,2,3); 

clEnqueueReadBuffer(queue, *d_data,...)// Error reading d_data 

나는 clCreateBuffer에 대한 clEnqueueMapBuffer 또는 CL_MEM_ALLOC_HOST_PTR을 시도, 그 중 하나가 작동하지 않습니다.

답변

1

cl_mem은 불투명 한 개체입니다. 포인터 연산을해서는 안됩니다. 그렇게하려고하면 매우 심한 버그가 발생합니다.

CUDA가 버퍼 할당을 처리하는 방법에 익숙하지 않지만 주석 처리 된 코드의 의미는 CUDA 버퍼가 항상 호스트에서 볼 수 있다는 것입니다. 이것은 매우 엄격하게 OpenCL의 경우가 아닙니다. OpenCL을 사용하면 버퍼를 호스트에서 볼 수있는 메모리로 "맵핑"할 수 있지만 호스트에서 암시 적으로 볼 수는 없습니다. 버퍼의 임의의 인덱스를 읽으려는 경우 먼저 맵핑하거나 호스트 데이터에 복사해야합니다.

float * h_data = new float[1000]; 
cl_mem d_buffer=clCreateBuffer(...); 

clEnqueueWriteBuffer(queue, d_buffer, true, 0, 1000 * sizeof(float), h_data, 0, nullptr, nullptr); 
//======OR====== 
//float * d_data = static_cast<float*>(clEnqueueMapBuffer(queue, d_buffer, true, CL_MAP_WRITE, 0, 1000 * sizeof(float), 0, nullptr, nullptr, nullptr)); 
//std::copy(h_data, h_data + 1000, d_data); 
//clEnqueueUnmapMemObject(queue, d_buffer, d_data, 0, nullptr, nullptr); 
//clEnqueueBarrier(queue); 

//Do work with buffer, probably in OpenCL Kernel... 

float result; 
size_t index = 1/2 * 3; //This is what you wrote in the original post 
clEnqueueReadBuffer(queue, d_buffer, true, index * sizeof(float), 1 * sizeof(float), &result, 0, nullptr, nullptr); 
//======OR====== 
//float * result_ptr = static_cast<float*>(clEnqueueMapBuffer(queue, d_buffer, true, CL_MAP_READ, index * sizeof(float), 1 * sizeof(float), 0, nullptr, nullptr, nullptr)); 
//result = *result_ptr; 
//clEnqueueUnmapMemObject(queue, d_buffer, result_ptr, 0, nullptr, nullptr); 
//clEnqueueBarrier(queue); 

std::cout << "Result was " << result << std::endl;