2012-11-25 60 views
4

我是openCL的新手,我試圖用一個非常簡單的內核開始。現在,我只是試圖將數據傳輸到內核並返回,以便我可以驗證正在設置的正確數據。但是,我變得非常奇怪的行爲。這裏是我的主代碼:OpenCL內存緩衝區傳輸給出不正確的數據

string PROGRAM_FILE = "C:\\Projects\\AnimatLabSDK\\OpenNeuronCL\\Libraries\\OpenNeuronCL\\Kernels\\FastSpikingNeuron.cl"; 
string KERNEL_FUNC = "FastSpikingNeuron"; 

std::vector<cl::Platform> platforms; 
std::vector<cl::Device> devices; 
int i; 

// Data 
cl::NDRange ndGlobal(DATA_SIZE); 
cl::NDRange ndLocal(LOCAL_SIZE); 

cl_float aryVmIn[DATA_SIZE], aryVmOut[DATA_SIZE]; 
cl_float aryVahp[DATA_SIZE], aryTestOut[DATA_SIZE]; 

try { 
    // Initialize data 
    for(i=0; i<DATA_SIZE; i++) { 
    aryVmIn[i] = i*0.1f; //0.0f; 
    aryVahp[i] = i*0.1f; //0.0f; 
    } 

    // Place the GPU devices of the first platform into a context 
    cl::Platform::get(&platforms); 
    platforms[0].getDevices(CL_DEVICE_TYPE_GPU, &devices); 
    cl::Context context(devices); 

    // Create kernel 
    std::ifstream programFile(PROGRAM_FILE); 
    std::string programString(std::istreambuf_iterator<char>(programFile), 
     (std::istreambuf_iterator<char>())); 
    cl::Program::Sources source(1, std::make_pair(programString.c_str(), 
     programString.length()+1)); 
    cl::Program program(context, source); 

    //std::cout << "Program kernel: " << std::endl << programString << std::endl; 

    try 
    { 
    program.build(devices); 
    } 
    catch(cl::Error e) 
    { 
     std::cout << e.what() << ": Error code " << e.err() << std::endl; 
     string buildlog; 
     program.getBuildInfo(devices[0], (cl_program_build_info)CL_PROGRAM_BUILD_LOG, &buildlog); 
     std::cout << "Error: " << buildlog << std::endl; 
     throw e; 
    } 

    cl::Kernel kernel(program, KERNEL_FUNC.c_str()); 

    // Create buffers 
    cl::Buffer bufferVmIn(context, CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, sizeof(aryVmIn), aryVmIn); 
    cl::Buffer bufferVmOut(context, CL_MEM_WRITE_ONLY, sizeof(aryVmOut), NULL); 
    cl::Buffer bufferVahp(context, CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, sizeof(aryVahp), aryVahp); 
    cl::Buffer bufferTestOut(context, CL_MEM_WRITE_ONLY, sizeof(aryTestOut), NULL); 

    // Set kernel arguments 
    kernel.setArg(0, bufferVmIn); 
    kernel.setArg(1, bufferVmOut); 
    kernel.setArg(2, bufferVahp); 
    kernel.setArg(3, bufferTestOut); 

    // Create queue and enqueue kernel-execution command 
    cl::CommandQueue queue(context, devices[0]); 

    queue.enqueueWriteBuffer(bufferVmIn, CL_TRUE, 0, sizeof(aryVmIn), aryVmIn, NULL, NULL); 
    queue.enqueueWriteBuffer(bufferVahp, CL_TRUE, 0, sizeof(aryVahp), aryVahp, NULL, NULL); 

    queue.enqueueNDRangeKernel(kernel, NULL, ndGlobal, ndLocal); 

    queue.enqueueReadBuffer(bufferVmOut, CL_TRUE, 0, sizeof(aryVmOut), aryVmOut, NULL, NULL); 
    queue.enqueueReadBuffer(bufferTestOut, CL_TRUE, 0, sizeof(aryTestOut), aryTestOut, NULL, NULL); 

    // Display updated buffer 
    for(i=0; i<10; i++) 
    { 
     printf("%6.5f, %6.5f", aryVmOut[i], aryTestOut[i]); 
     printf("\n"); 
    } 
} 
catch(cl::Error e) 
{ 
    std::cout << e.what() << ": Error code " << e.err() << std::endl; 
} 

這裏是我的內核:

__kernel void FastSpikingNeuron(__global float *aryVmIn, __global float *aryVmOut, __global float *aryVahp, __global float *aryTestOut) 
{ 
int gid = get_global_id(0); 
local float fltVahp; 

fltVahp = aryVahp[gid]; 

aryVmOut[gid] = fltVahp; 
aryTestOut[gid] = fltVahp; 
} 

我只是設置一些數據,然後試圖讀出Vmout和TESTOUT然後查看他們的一些內容。當我運行這個應用程序時,我得到以下輸出:

0.00000, 0.90000 
0.10000, 0.90000 
0.20000, 0.90000 
0.30000, 0.90000 
0.40000, 0.90000 
0.50000, 0.90000 
0.60000, 0.90000 
0.70000, 0.90000 
0.80000, 0.90000 
0.90000, 0.90000 

到目前爲止,這對我沒有任何意義。在內核中,我將VmOut和TestOut設置爲完全相同的變量,但是當我將它讀回主機時,我得到了不同的結果。我在這裏做錯了事,但我還沒有弄清楚它是什麼。任何在opencl方面經驗豐富的人的幫助都會很感激。

感謝 大衛

+0

如果交換內核的最後兩行,會發生什麼? – Thomas

回答

2

您的內核,造成有多個工作項存儲不同的值相同的內存位置,這就是爲什麼你得到奇怪的結果的競爭條件。

提醒 - 的local地址空間的定義是:

的__local或本地地址空間的名字被用來描述需要被 在本地內存中分配的變量,並所有工作項共享的工作組

如果要爲每個工作項目設置不同的值,只需省略local修飾符。