OpenCL 学习step by step (5) 使用二维NDRange workgroup

简介: 在本教程中,我们使用二维NDRange来设置workgroup,这样在opencl中,workitme的组织形式是二维的,Kernel中 的代码也要做相应的改变,我们先看一下clEnqueueNDRangeKernel函数的变化。

      在本教程中,我们使用二维NDRange来设置workgroup,这样在opencl中,workitme的组织形式是二维的,Kernel中 的代码也要做相应的改变,我们先看一下clEnqueueNDRangeKernel函数的变化。首先我们指定了workgroup size为localx*localy,通常这个值为64的倍数,但最好不要超过256。

//执行kernel,Range用2维,work itmes size为width*height,
cl_event ev;
size_t globalThreads[] = {width, height};
size_t localx, localy;
if(width/8 > 4)
    localx = 16;
else if(width < 8)
    localx = width;
else localx = 8;

if(height/8 > 4)
    localy = 16;
else if (height < 8)
    localy = height;
else localy = 8;

size_t localThreads[] = {localx, localy}; // localx*localy应该是64的倍数
printf("global_work_size =(%d,%d), local_work_size=(%d, %d)\n",width,height,localx,localy);

clTimer.Reset();
clTimer.Start();
clEnqueueNDRangeKernel( queue,
    kernel,
    2,
    NULL,
    globalThreads,
    localThreads, 0, NULL, &ev);

注意:在上面代码中,定义global threads以及local threads数量,都是通过二维数组的方式进行的。

    新的Kernel代码如下:

#pragma OPENCL EXTENSION cl_amd_printf : enable

__kernel void vecadd(__global const float* a, __global const float* b, __global float* c)
{
int x = get_global_id(0);
int y = get_global_id(1);
int width = get_global_size(0);
int height = get_global_size(1);
if(x == 1 && y ==1)
printf("%d, %d,%d,%d,%d,%d\n",get_local_size(0),get_local_size(1),get_local_id(0),get_local_id(1),get_group_id(0),get_group_id(1));

c[x + y * width] = a[x + y * width] + b[x + y * width];

}

      我们在kernel中增加了#pragma OPENCL EXTENSION cl_amd_printf : enable,以便在kernel中通过printf函数进行debug,这是AMD的一个扩展。printf还可以直接打印出float4这样的向量,比如printf(“%v4f”, vec)。

      另外,在main.cpp中增加一行代码:

//告诉driver dump il和isa文件
_putenv("GPU_DUMP_DEVICE_KERNEL=3");

      我们可以在程序目录dump出il和isa形式的kernel文件,对于熟悉isa汇编的人,这是一个很好的调试performance的方法。

     在最新的app sdk 2.7及以后的sdk中,在kernel中使用printf的时候,这个程序会hang在哪儿,以前没这种情况。

程序执行界面。

image

完整的代码请参考:

工程文件gclTutorial4

代码下载:

http://files.cnblogs.com/mikewolf2002/gclTutorial.zip

相关文章
|
存储 传感器 安全
「Arm Arch」 初识 Arm(下)
「Arm Arch」 初识 Arm(下)
1519 0
|
数据可视化 关系型数据库 编译器
【C/C++ 单线程性能分析工具 Gprof】 GNU的C/C++ 性能分析工具 Gprof 使用全面指南
【C/C++ 单线程性能分析工具 Gprof】 GNU的C/C++ 性能分析工具 Gprof 使用全面指南
2179 2
|
6月前
|
人工智能 安全 API
2026年OpenClaw Skills选型指南:52个官方Skill+5700社区Skill部署及验真测评
2026年,OpenClaw(原Clawdbot、Moltbot)凭借开放的Skill生态成为AI助手领域的焦点,ClawHub平台上汇聚的5705个技能覆盖从办公自动化到智能家居的全场景需求。但光鲜背后暗藏风险:Koi Security审计发现至少341个恶意Skill,Bitdefender扫描显示近20%存在安全问题,VirusTotal对3016个Skill的分析更是揭露数百个含恶意特征的插件。这些恶意Skill伪装成加密钱包追踪器、YouTube摘要工具等实用工具,后台却窃取API Key、开启反向Shell远程控制设备,成为隐藏的安全隐患。
6459 2
|
11月前
|
负载均衡 算法 调度
基于遗传算法的新的异构分布式系统任务调度算法研究(Matlab代码实现)
基于遗传算法的新的异构分布式系统任务调度算法研究(Matlab代码实现)
402 11
|
存储 人工智能 编译器
【AI系统】算子手工优化
本文深入探讨了手写算子调度的关键因素及高性能算子库的介绍,通过计算分析指标和 RoofLine 模型评估计算与访存瓶颈,提出了循环、指令、存储三大优化策略,并介绍了 TVM 和 Triton 两种 DSL 开发算子的方法及其在实际应用中的表现。
1557 2
【AI系统】算子手工优化
|
IDE 开发工具 C++
CMake中文手册_target_sources(3.26)
CMake中文手册_target_sources(3.26)
1486 0
|
机器学习/深度学习 算法 文件存储
神经架构搜索:自动化设计神经网络的方法
在人工智能(AI)和深度学习(Deep Learning)快速发展的背景下,神经网络架构的设计已成为一个日益复杂而关键的任务。传统上,研究人员和工程师需要通过经验和反复试验来手动设计神经网络,耗费大量时间和计算资源。随着模型规模的不断扩大,这种方法显得愈加低效和不够灵活。为了解决这一挑战,神经架构搜索(Neural Architecture Search,NAS)应运而生,成为自动化设计神经网络的重要工具。
1061 0
|
缓存 负载均衡 Java
c++写高性能的任务流线程池(万字详解!)
本文介绍了一种高性能的任务流线程池设计,涵盖多种优化机制。首先介绍了Work Steal机制,通过任务偷窃提高资源利用率。接着讨论了优先级任务,使不同优先级的任务得到合理调度。然后提出了缓存机制,通过环形缓存队列提升程序负载能力。Local Thread机制则通过预先创建线程减少创建和销毁线程的开销。Lock Free机制进一步减少了锁的竞争。容量动态调整机制根据任务负载动态调整线程数量。批量处理机制提高了任务处理效率。此外,还介绍了负载均衡、避免等待、预测优化、减少复制等策略。最后,任务组的设计便于管理和复用多任务。整体设计旨在提升线程池的性能和稳定性。
507 5
|
编译器 C++
使用Visual Studio 2022 创建lib和dll并使用
本文介绍了如何在Visual Studio 2022中创建静态库(lib)和动态库(dll),并展示了如何使用这些库。文章详细说明了创建新项目、编写代码、生成库文件、配置项目属性以及编写测试代码的步骤,并提供了相应的截图和代码示例。作者还分享了在创建和使用库的过程中遇到的一些问题及其解决方案。
5530 0
使用Visual Studio 2022 创建lib和dll并使用
|
存储 Linux 程序员
tar命令详解:linux文件打包神器
tar命令详解:linux文件打包神器
1397 1