OpenCL 编程步骤 3. 获取Context 上下文

news/2024/12/20 11:25:15/文章来源:https://www.cnblogs.com/turbinee/p/18618951

转载 https://deepinout.com/opencl/opencl-basic-tutorials/opencl-create-context.html

上下文为关联的设备、内存对象、命令队列、程序对象、内核对象提供一个容器。上下文是OpenCL应用的核心。正是上下文驱动着应用程序与特定设备以及特定设备之间的通信。

对于上下文中关联的所有计算设备必须全都来自于同一平台,对于来自不同平台的OpenCL设备,需要为各个平台独立地创建上下文。对于同一平台的设备,上下文中可以关联多个设备。主机应用也可以使用多个上下文来管理多个设备,甚至同一个平台多个设备都可以关联到不同的上下文,如下图所示。

在上图中,平台1有多个CPU和GPU设备。同一平台的设备可以关联到同一上下文中,所以上下文1、上下文2中关联CPU和GPU设备是可行的。

对于平台中的设备,上下文不是非要关联所有的设备,所以在上下文4中只是关联了部分设备。而不同平台的设备不能关联到同一上下文中,所以关联平台1中的GPU3和平台2中的CPU1的上下文3是不合法的。

个人理解:

  • 平台对上下文,一对多
  • 同一平台的设备对上下文,多对一

OpenCL 创建上下文

OpenCL上下文对象用cl_context类型表示,可以使用如下两个函数其中之一来创建上下文:

cl_context clCreateContext(const cl_context_properties *properties,cl_uint num_devices ,const cl_device_id *devices ,void (CL_CALLBACK *pfn_notify )(const char *, const void *, size_t, void *),void *user_data ,cl_int *errcode_ret )cl_context clCreateContextFromType(const cl_context_properties *properties,cl_device_type device_type ,void (CL_CALLBACK *pfn_notify )(const char *, const void *, size_t, void *),void *user_data,cl_int *errcode_ret)

两个函数用法很类似,主要的区别在于:

  • clCreateContext显示地指定设备(devices)来创建上下文;
  • clCreateContextFromType根据给定的设备类型(device_type)来创建上下文。对设备类型详见下表。

参数properties指定上下文属性名称及属性相应的值的列表,且最后一个元素为0,见下表。当实现自定义选择平台时,参数properties可以设置为NULL。

参数pfn_notify和user_data用来共同定义一个回调函数,可以调用这个回调报告上下文生命周期中出现错误的有关信息,要把user_data作为最后一个参数传至回调函数。user_data为void类型指针,也就是可以指向任何数据,当错误发生时user_data能够提供信息。参数pfn_notf iy和user_data也都可以设置为NULL。参数errcode_ret为函数的返回状态,成功执行值为CL_SUCCESS,否则值为对应的错误代码。

下面的代码清单展示了给定一个平台,查询平台中GPU设备,并创建上下文:

cl_device_id *device;
cl_platform_id platform;
cl_int err;
cl_uint NumDevice;//选择第一个平台
err = clGetPlatformIDs(1, &platform, NULL);
err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 0, NULL, &NumDevice);
device = (cl_device_id *)malloc(sizeof(cl_device_id) *NumDevice);//选择GPU设备
err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, NumDevice, device, NULL);//创建上下文
cl_context_properties properites[] = {CL_CONTEXT_PLATFORM, (cl_context_properties)platform, 0};//指定设备创建上下文
//cl_context
context=clCreateContext(properites,NumDevice,device,NULL,NULL,&err);//指定设备类型创建上下文
cl_context context = clCreateContextFromType(properites, CL_DEVICE_TYPE_GPU, NULL, NULL, &err);

例子中,clCreateContext函数把平台中查询到的所有GPU设备都关联到创建的上下文中。clCreateContextFromType则是选择第一平台中的GPU设备。从功能来说,两个函数实现的功能是一样的。

clGetContextInfo

给定上下文,可以使用如下函数查询上下文各个属性信息:

cl_int clGetContextInfo(cl_context      context ,cl_context_info param_name ,size_t          param_value_size ,void            *param_value ,size_t          *param_value_size_ret )

参数param_name为查询属性名称,取值见下表,参数param_value返回上下文查询属性信息。

下面的代码清单展示了使用clContextInfo()查询上下文关联的设备数目及上下文的引用计数方法:

cl_platform_id platform;
cl_int err;
cl_uint NumDevice;err = clGetPlatformIDs(1, &platform, NULL);
cl_context_properties properites[] = {CL_CONTEXT_PLATFORM, (cl_context_properties)platform, 0};
cl_context context = clCreateContextFromType(properites, CL_DEVICE_TYPE_ALL, NULL, NULL, &err);NumDevice = 0;
size_t DeviceSize;
err = clGetContextInfo(context, CL_CONTEXT_NUM_DEVICES, sizeof(cl_uint), &NumDevice, NULL);printf("Number of Device in context:%d\n", NumDevice);

上述代码片段中,在调用函数clContextInfo时,对其参数param_name指定的是CL_CONTEXT_NUM_DEVICES,从字面上理解非常直观,即我们要查询当前上下所包含的计算设备个数。除了可指定CL_CONTEXT_NUM_DEVICES这个属性以外,还能指定CL_CONTEXT_REFERENCE_COUNT这一属性,表示查询当前上下文的引用计数值。在之前我们没有讲解任何关于OpenCL中引用计数的概念,那这个引用计数到底是什么?它又有何作用呢?

在使用clCreateContext或clCreateContextFromType创建上下文时,并不像我们之前创建平台和设备时返回错误代码,而是直接返回cl_context对象,此时该上下文对象的引用计数为1。

其实,OpenCL对很多对象采用了类似于Apple的Cocoa Framework中的内存管理机制(毕竟OpenCL的初稿出自Apple)。在这种机制下,主张谁分配了某个对象,那么谁就负责释放该对象。如果这个对象不是由你来分配的,那么你也不用去释放它。我们通过OpenCL接口就能看出哪些对象是被分配的,哪些不是。例如,clGetPlatformIDs函数所获得的platform_id对象就不需要通过某个接口进行释放,因为它是通过Get获得的。

类似的是, clGetDeviceIDs也同样如此。这里的clCreateContext我们看到用的是Create这个前缀,当我们看到这个前缀时就要想到一定有一个与之相对应的Retain接口和Release接口。Retain接口用于显式地做引用计数加1操作;而Release则是显式地做引用计数减1操作,而只有当引用计数为0时,Release操作才会释放对应的空间。而引入这个引用计数机制对于第三方库或者跨模块的开发非常有利。例如,我们在模块A创建了一个上下文,然后在做完某个计算后把它提交给模块B继续计算。

当然,出于性能要求,模块B借用了这个上下文对象之后可能会自己另建一个命令队列然后执行,因此与模块A的后续操作完全可以是异步的。这就会引发一个问题,当模块A执行完之后,把该上下文对象释放掉,而模块B此时还在使用这个上下文对象。因此,如果没有引用计数,而是直接把此上下文对象释放掉,那么模块B在使用此对象时就可能会引发异常。而有了引用计数机制,我们可以遵循这个机制来做——在模块A中创建上下文对象,那么在A用完之后通过Release接口将它释放。如果要把此对象交给模块B做后续操作,那么要由模块B对此对象做一次Retain操作,然后模块B操作完成之后也要调用一次Release操作来释放此上下文对象。这样一来,上下文对象就能安全而又完整地被模块A与模块B共同使用了。

上下文对象的Retain和Release接口

对于上下文对象的Retain和Release接口如下:

cl_int clRetainContext(cl_context context )
cl_int clReleaseContext(cl_context context )

clRetainContext增加引用计数(引用计数+1),clReleaseContext减少引用计数(引用计数-1)。如果外部函数访问预先创建的上下文,确保在处理前调用clRetainContext,处理完成后调用clReleaseContext。如果在创建上下文的函数中,在函数完成前调用clReleaseContext来减少引用计数,使其值为0,释放上下文空间。

下面的代码展示了这两个函数的使用方式:

…
cl_context_properties properites[] = {CL_CONTEXT_PLATFORM, (cl_context_properties)platform, 0};
cl_context context = clCreateContextFromType(properites, CL_DEVICE_TYPE_ALL, NULL, NULL, NULL);cl_uint ReferenCount;
clGetContextInfo(context, CL_CONTEXT_REFERENCE_COUNT, sizeof(cl_uint), &ReferenCount, NULL);
printf("Initial Reference Count: %d\n ", ReferenCount);clRetainContext(context);
clGetContextInfo(context, CL_CONTEXT_REFERENCE_COUNT, sizeof(cl_uint), &ReferenCount, NULL);
printf("Reference Count: %d\n ", ReferenCount);clReleaseContext(context);
clGetContextInfo(context, CL_CONTEXT_REFERENCE_COUNT, sizeof(cl_uint), &ReferenCount, NULL);
printf("Reference Count: %d\n ", ReferenCount);

如上代码,输出为:

Initial Reference Count:1
Reference Count:2
Reference Count:1

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/855768.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Gitlab runner持续集成CI/CD怎么设置标签指定Runner节点执行

搭建Runner参考: https://www.cnblogs.com/minseo/p/18472436 需求:未打标签的.gitlab-ci使用默认runner 打标签的.gitlab-ci使用指定的runner环境查看 系统环境# cat /etc/redhat-release Rocky Linux release 9.3 (Blue Onyx) # uname -a Linux Rocky9StoneCrm003080 5.14.…

应用内自动续订商品,畅享无缝服务体验

用户购买某种产品时习惯一次性付款,但是对开发者而言,单次购买模式或需要用户频繁续订的服务可能会导致收入不稳定,无法获得持续稳定的收入。对于有视频、音乐等会员需求的用户,一旦体验到服务中断或需要频繁操作,可能会转向其他竞争产品,导致用户流失。 HarmonyOS SDK应…

一文学会powshell使用及功能

声明! 原文来自微信公众号泷羽Sec-track认识powsehll PowerShell(通常称作PowerShell或Windows PowerShell)是由微软开发的一种任务自动化和配置管理框架,与linux命令相似,它结合了命令行外壳和脚本语言功能,使得系统管理员和用户能够更高效地管理系统和自动化任务。 打开…

OpenAi 大模型生态体系介绍

OpenApi大模型家族介绍模型概览 多模态大模型 能够理解和生成自然语言或代码+理解图像+生成图像等 GPT-4是一个大型多模态模型(接受文本或图像输入并输出文本),它可以比我们以前的任何模型都更准确地解决难题这得益于它更广泛的通用知识和更高级的推理能力。GPT-4可在OpenAIAP…

configure: error: curses development files not found

001、报错如下: configure: error: curses development files not found 002、rocky9系统[root@PC1 samtools-1.21]# cat /etc/redhat-release Rocky Linux release 9.4 (Blue Onyx) 003、解决方法[root@PC1 samtools-1.21]# dnf install ncurses-devel.x86_64 -y 004、配置…

动画图解嵌入式常见的通讯协议:SPI、IC、UART、红外

文章下方附学习资源,自助领取。 1 SPI传输 ▲ 图1 SPI 数据传输 ▲ 图1.2 SPI数据传输(2) ▲ 图1.3 SPI时序信号 2 IC传输 ▲ 图1.2.1 I2C总线以及寻址方式3年嵌入式物联网学习资源整理分享:C语言、Linux开发、数据结构;软件开发,STM32单片机、ARM硬件开发、物联网通…

SQL71 牛客每个人最近的登录日期(六)

描述 牛客每天有很多人登录,请你统计一下牛客每个用户查询刷题信息,包括: 用户的名字,以及截止到某天,累计总共通过了多少题。 不存在没有登录却刷题的情况,但是存在登录了没刷题的情况,不会存在刷题表里面,有提交代码没有通过的情况,但是会记录在刷题表里,只不过通过…

趣味管理

最近和人聊天,讲到过去的光荣历程,以及现在的状况,最后他抛出了一个管理上的问题,很有意思。我做了个示意图,方便大家思考。 先做下说明,大圆是他的企业,中心是老板,第一圈是高层管理,第二卷是中低层管理,第三圈就是员工了。

第三次使用

每个销声匿迹的人 都在打着这辈子最硬的一场仗。

chrome浏览器如何恢复最近关闭的页面

前言 大家好,我是小徐啊。谷歌chrome浏览器是我们在开发Java应用的时候,常用的浏览器。这个浏览器功能十分强大,非常适合我们进行开发调试代码。有时候,我们打开了一个页面,但由于手误关闭了,或者关闭了,想再恢复,有没有好的办法呢?其实是有的。今天,小徐就来介绍下如…

5.8K star!基于Go的可视化定时任务管理系统!

* 戳上方蓝字“开源先锋”关注我推荐阅读:《12.6K star!Shell命令即搞定可视化监控,超级6~~》《5.6K star!再见了DocSend,这款开源项目更不错!》《4.1K star!跨屏操作的神器,流畅丝滑!》《9.1K star!国外大神1:1复刻Win11系统,开源牛逼!》《2.8K star!超强音乐管理…

Cookie和会话安全详解

本文为《白帽子Web讲安全(第2版)》——Cookie和会话安全章节的阅读总结及摘录,详述了Cookie的定义及Cookie的相关属性,概述了安全使用Cookie的方法等。一、Cookie与会话的定义Cookie是Web服务端发送给用户浏览器的一小段数据,浏览器会存储这些数据,并在后续发往服务器的请求…