2016-03-01 61 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中进行了投射。