2016-03-01 60 views
2
////////////////////////////////// 
// host code 
////////////////////////////////// 

// ... 
// select device/create context/build program 
// ... 

cl_kernel k_func_Test = nullptr; 

k_func_Test = clCreateKernel(prog, "k_Test", &error); 

size_t localsize = 3; 
size_t globalsize = localsize * 2; 

error = clEnqueueNDRangeKernel(command_queue, k_func_Test, 1, NULL, &globalsize_, &localsize_, 0, nullptr, nullptr); 

clFinish(command_queue); 

////////////////////////////////// 
// kernel code 
////////////////////////////////// 

__kernel void k_Test() 
{ 
    if ((get_group_id(0) + get_group_id(1) + get_group_id(2)) == 0 && 
     (get_local_id(0) + get_local_id(1) + get_local_id(2)) == 0) 
    { 
     printf("get_global_size = %d x %d x %d | " \ 
       "get_local_size = %d x %d x %d | " \ 
       "get_work_dim = %d \n" \ 
       "////////////////////////////////////\n", \ 
       get_global_size(0), get_global_size(1), get_global_size(2), \ 
       get_local_size(0), get_local_size(1), get_local_size(2), \ 
       get_work_dim() 
       ); 
    } 

    printf("get_group_id = %d x %d x %d \n" \ 
      "get_global_id = %d x %d x %d \n" \ 
      "get_local_id = %d x %d x %d \n" \ 
      "get_num_groups = %d x %d x %d \n" \ 
      "////////////////////////////////////\n", \ 
      get_group_id(0), get_group_id(1), get_group_id(2), \ 
      get_global_id(0), get_global_id(1), get_global_id(2), \ 
      get_local_id(0), get_local_id(1), get_local_id(2), \ 
      get_num_groups(0), get_num_groups(1), get_num_groups(2) 
      ); 
} 

不同工作內核代碼我有3個裝置:的OpenCL:爲x86和x64版本

1)英特爾(R)核心(TM)i7-4790K CPU @ 4.00GHz

2)英特爾(R)HD顯卡4600

3)的GeForce GTX 780鈦

爲x86的所有設備我得到這些結果:

//////////////////////////////////// 
get_global_size = 6 x 1 x 1 | get_local_size = 3 x 1 x 1 | get_work_dim = 1 
//////////////////////////////////// 
get_group_id = 1 x 0 x 0 
get_global_id = 3 x 0 x 0 
get_local_id = 0 x 0 x 0 
get_num_groups = 2 x 1 x 1 
//////////////////////////////////// 
get_group_id = 1 x 0 x 0 
get_global_id = 4 x 0 x 0 
get_local_id = 1 x 0 x 0 
get_num_groups = 2 x 1 x 1 
//////////////////////////////////// 
get_group_id = 1 x 0 x 0 
get_global_id = 5 x 0 x 0 
get_local_id = 2 x 0 x 0 
get_num_groups = 2 x 1 x 1 
//////////////////////////////////// 
get_group_id = 0 x 0 x 0 
get_global_id = 0 x 0 x 0 
get_local_id = 0 x 0 x 0 
get_num_groups = 2 x 1 x 1 
//////////////////////////////////// 
get_group_id = 0 x 0 x 0 
get_global_id = 1 x 0 x 0 
get_local_id = 1 x 0 x 0 
get_num_groups = 2 x 1 x 1 
//////////////////////////////////// 
get_group_id = 0 x 0 x 0 
get_global_id = 2 x 0 x 0 
get_local_id = 2 x 0 x 0 
get_num_groups = 2 x 1 x 1 
//////////////////////////////////// 

但是,我開始爲x64我得到了非常不同的結果。對於「英特爾(R)高清顯卡4600」 - 結果與x86版本相同。

但對於 「英特爾(R)酷睿(TM)i7-4790K CPU @ 4.00GHz」 和 「的GeForce GTX 780鈦」 我得到了如下結果:

//////////////////////////////////// 
get_global_size = 6 x 0 x 1 | get_local_size = 0 x 1 x 0 | get_work_dim = 3 
//////////////////////////////////// 
get_group_id = 1 x 0 x 0 
get_global_id = 0 x 0 x 0 
get_local_id = 3 x 0 x 0 
get_num_groups = 0 x 0 x 0 
//////////////////////////////////// 
get_group_id = 1 x 0 x 0 
get_global_id = 0 x 0 x 0 
get_local_id = 4 x 0 x 0 
get_num_groups = 0 x 0 x 0 
//////////////////////////////////// 
get_group_id = 1 x 0 x 0 
get_global_id = 0 x 0 x 0 
get_local_id = 5 x 0 x 0 
get_num_groups = 0 x 0 x 0 
//////////////////////////////////// 
get_group_id = 0 x 0 x 0 
get_global_id = 0 x 0 x 0 
get_local_id = 0 x 0 x 0 
get_num_groups = 0 x 0 x 0 
//////////////////////////////////// 
get_group_id = 0 x 0 x 0 
get_global_id = 0 x 0 x 0 
get_local_id = 1 x 0 x 0 
get_num_groups = 0 x 0 x 0 
//////////////////////////////////// 
get_group_id = 0 x 0 x 0 
get_global_id = 0 x 0 x 0 
get_local_id = 2 x 0 x 0 
get_num_groups = 0 x 0 x 0 
//////////////////////////////////// 

因此,正如我們所看到的結果的非常不同。例如在函數「clEnqueueNDRangeKernel」中,我們設置了參數work_dim = 1,但我不明白爲什麼對於x64版本的應用程序 - 它的工作方式不同!和get_work_dim()得到1或3(最後我想得到local_work_size的值)。

也許有人遇到過這個?執行不同的驅動程序?它是什麼?

回答

1

我相信你的問題在這裏可能是你在調用printf時使用的格式說明符。 OpenCL C內置函數get_global_size(),get_local_size(),get_num_groups(),get_global_id(),get_local_id()和get_group_id()都返回size_t值。 size_t類型根據體系結構的地址寬度而不同,它的大小等於指針的大小(即sizeof(size_t)== sizeof(void *)),因此在x86上size_t是4bytes,在x86_64上size_t是8bytes。由於這個printf具有size_t值的「%zu」格式說明符。這可能可以解釋爲什麼在x86和x86_64內核版本上看到不同的輸出。

此外,OpenCL C內置的get_work_dim()返回一個無符號的int值,因此您應該使用「%u」格式說明符。

也許嘗試這爲您的內核,而不是:

__kernel void k_Test() 
{ 
    if ((get_group_id(0) + get_group_id(1) + get_group_id(2)) == 0 && 
     (get_local_id(0) + get_local_id(1) + get_local_id(2)) == 0) 
    { 
     printf("get_global_size = %zu x %zu x %zu | " \ 
       "get_local_size = %zu x %zu x %zu | " \ 
       "get_work_dim = %u \n" \ 
       "////////////////////////////////////\n", \ 
       get_global_size(0), get_global_size(1), get_global_size(2), \ 
       get_local_size(0), get_local_size(1), get_local_size(2), \ 
       get_work_dim() 
       ); 
    } 

    printf("get_group_id = %zu x %zu x %zu \n" \ 
      "get_global_id = %zu x %zu x %zu \n" \ 
      "get_local_id = %zu x %zu x %zu \n" \ 
      "get_num_groups = %zu x %zu x %zu \n" \ 
      "////////////////////////////////////\n", \ 
      get_group_id(0), get_group_id(1), get_group_id(2), \ 
      get_global_id(0), get_global_id(1), get_global_id(2), \ 
      get_local_id(0), get_local_id(1), get_local_id(2), \ 
      get_num_groups(0), get_num_groups(1), get_num_groups(2) 
      ); 
} 
0

是,AerialMantis權利!內核上的函數printf的問題。在函數Test()中對工作函數中的更改相同並在所有平臺上進行預測後。

__kernel void k_Test() 
{ 
    if ((get_group_id(0) + get_group_id(1) + get_group_id(2)) == 0 && 
     (get_local_id(0) + get_local_id(1) + get_local_id(2)) == 0) 
    { 
     printf("get_global_size = %d x %d x %d | " \ 
       "get_local_size = %d x %d x %d | " \ 
       "get_work_dim = %d \n" \ 
       "////////////////////////////////////\n", \ 
       (int)get_global_size(0), (int)get_global_size(1), (int)get_global_size(2), \ 
       (int)get_local_size(0), (int)get_local_size(1), (int)get_local_size(2), \ 
       (int)get_work_dim() 
       ); 
    } 

    printf("get_group_id = %d x %d x %d \n" \ 
      "get_global_id = %d x %d x %d \n" \ 
      "get_local_id = %d x %d x %d \n" \ 
      "get_num_groups = %d x %d x %d \n" \ 
      "////////////////////////////////////\n", \ 
      (int)get_group_id(0), (int)get_group_id(1), (int)get_group_id(2), \ 
      (int)get_global_id(0), (int)get_global_id(1), (int)get_global_id(2), \ 
      (int)get_local_id(0), (int)get_local_id(1), (int)get_local_id(2), \ 
      (int)get_num_groups(0), (int)get_num_groups(1), (int)get_num_groups(2) 
      ); 
} 

繼建議,並使用%u和%祖格式說明我寫了如下代碼:

__kernel void k_Test2() 
{ 
    printf("get_work_dim = %u get_global_id = %zu x %zu x %zu \n", get_work_dim(), get_global_id(0), get_global_id(1), get_global_id(2)); 
} 

並理解:符%U - 作品! %zu - 不適用於所有平臺。例如,英特爾HD返回「無效表達式:(空)錯誤:printf引發異常」。所以我通過添加前綴(int)在函數k_Test中進行了投射。