clCreateBuffer和clCreateBuufer + clEnqueueWriteBuffer


有兩種方式實現從主機到CL設備的數據傳遞,
第一種:

cl_mem input = clCreateBuffer(context,CL_MEM_READ_ONLY,sizeof(float) * DATA_SIZE, NULL, NULL);
clEnqueueWriteBuffer(command_queue, input, CL_TRUE, 0, sizeof(float) * DATA_SIZE, inputdata, 0, NULL, NULL);

第二種:

cl_mem input = clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(float) * DATA_SIZE, inputdata, NULL);
  • 這兩種寫法可以說是沒啥區別,但是如過第二中寫法中CL_MEM_COPY_HOST_PTR換成CL_MEM_USE_HOST_PTR,那么根據文檔的說法,第二種並不會把主機的inputdata復制到設備,而僅僅是cache
  • 如果inputdata僅僅會初始化一次,那么使用第二種方法看起來更加便捷;但是如果對inputdata要進行多次更新,那么使用第一種的方式更好,可以調用clEnqueueWriteBuffer進行更新
  • 使用第一種可以在clEnqueueWriteBuffer中使用event來測量耗時
  • 第一種寫法會先在主機創建一個second temporary buffer on the host,然后等到設置這個buffer到kernel的時候再把數據拷貝到設備上。這樣,就可能會在一個短暫的時候,主機上有兩份內存。如果buffer比較大,就會引發問題。而第二種方法則是立即把數據復制的設備,沒有額外的臨時內存分配。參考
  • 如果clcontext上綁定了多個device,那么使用第二種方法則會在每個device上都分配該buffer。如果只想對某個設備分配該buffer,那么就應該使用與device綁定了的clEnqueueWriteBuffer參考
  • 然而,在高通的優化指南中,這兩種做法都不推薦。推薦使用Zero Copy的寫法,其關鍵在於CL_MEM_ALLOC_HOST_PTR的應用
// First set cl_mem_flags input in clCreateBuffer:
cl_mem Buffer = clCreateBuffer(context,
    CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR,
    sizeof(cl_ushort) * size,
    NULL,
    &status);
//Then use the map function to return a pointer to the host:
cl_uchar *hostPtr = (cl_uchar *)clEnqueueMapBuffer(
    commandQueue,
    Buffer,
    CL_TRUE,
    CL_MAP_WRITE,
    0,
    sizeof(cl_uchar) * size,
    0, NULL, NULL, &status);

//Host updates the buffer using the pointer hostPtr
    memcpy(hostPtr, sizeof(cl_uchar) * size, datafromhost);
    
//Unmapped the object
status = clEnqueueUnmapMemObject(
    commandQueue,
    Buffer,
    (void *) hostPtr,
    0, NULL, NULL);
    
//The object can be used by OpenCL kernels


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



猜您在找
 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM