OpenCL:x86 和 x64 版本的不同工作内核代码
OpenCL: different work kernel code for the x86 and x64 versions
//////////////////////////////////
// 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 台设备:
1) 英特尔® 酷睿™ i7-4790K CPU @ 4.00GHz
2) 英特尔® 核芯显卡 4600
3) GeForce GTX 780 Ti
对于 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开始,我得到了非常不同的结果。对于"英特尔® 核芯显卡 4600" - 结果与 x86 版本相同。
但是对于"Intel(R) Core(TM) i7-4790K CPU @ 4.00GHz"和"GeForce GTX 780 Ti",我得到了以下结果:
////////////////////////////////////
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 的值)。
也许有人经历过这个? 实现不同的驱动程序?这是什么?
您在这里的问题可能在于您在调用 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是 4 字节,在 x86_64 size_t 上是 8 字节。因此,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)
);
}
是的,空中螳螂的权利!函数在内核上的 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 和 %zu 格式说明符以下代码:
__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中进行了强制转换。
- QSqlquery prepare()和bindvalue()不工作
- 导入库可以跨dll版本工作吗
- 以螺旋方式打印矩阵的程序.(工作不好)
- 对象指针在c++中是如何工作的
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- VSOMEIP-2个设备之间的通信(TCP/UDP)不工作
- 如何在内核C++中使用1920x1080x16M图形或类似的16M颜色?(VGA)
- 为字符串中每 N 个字符插入空格的函数没有按照我认为的方式工作?
- C++为线程工作动态地分割例程
- 为什么我的 std::ref 无法按预期工作?
- 布尔比较运算符是如何在C++中工作的
- CUDA内核和数学函数的显式命名空间
- CUDA内核printf()在终端中不产生输出,在探查器中工作
- Ubuntu,如何找到内核工作繁重的程序热点?似乎kernel.kallsyms上的函数没有标记为用户空间函数的子级
- CUDA并发内核启动不工作
- OpenCL:x86 和 x64 版本的不同工作内核代码
- 嵌入式 linux/android 内核开发工作流程
- 内核可以工作,但不应该
- 链接内核后跳转到保护模式不工作
- 如何在CUDA内核中工作