CUDA独立上下文模块加载

CUDA独立上下文模块加载

在这里插入图片描述

大多数 CUDA 开发人员都熟悉 cuModuleLoad API 及其对应项,用于将包含设备代码的模块加载到 CUDA 上下文中。 在大多数情况下,您希望在所有设备上加载相同的设备代码。 这需要将设备代码显式加载到每个 CUDA 上下文中。 此外,不控制上下文创建和销毁的库和框架必须跟踪它们以显式加载和卸载模块。

这篇文章讨论了 CUDA 12.0 中引入的上下文独立加载,它解决了这些问题。

上下文相关的加载(Context-dependent loading)

传统上,模块加载总是与 CUDA 上下文相关联。 下面的代码示例显示了将相同的设备代码加载到两个设备然后在它们上启动内核的传统方法。

// Device 0
cuDeviceGet(&device0, 0);
cuDevicePrimaryCtxRetain(&ctx0, device0);
cuModuleLoad(&module0, “myModule.cubin”);
// Device 1
cuDeviceGet(&device1, 1);
cuDevicePrimaryCtxRetain(&ctx1, device1);
cuModuleLoad(&module1, “myModule.cubin”);

在每个设备上启动内核需要您检索每个模块的 CU 函数,如以下代码示例所示:

// Device 0
cuModuleGetFuntion(&function0, module0, “myKernel”);
cuLaunchKernel(function0,);
// Device 1
cuModuleGetFuntion(&function1, module1, “myKernel”);
cuLaunchKernel(function1,);

这会增加应用程序中的代码复杂性,因为您必须检索和跟踪每个上下文和每个模块的类型。 您还必须使用 cuModuleUnload API 显式卸载每个模块。

当库或框架主要使用 CUDA 驱动程序 API 来加载它们自己的模块时,问题会加剧。 他们可能无法完全控制应用程序拥有的上下文的生命周期。

// Application codelibraryInitialize();
cuDevicePrimaryCtxRetain(&ctx0, device0);
libraryFunc();
cuDevicePrimaryCtxRetain(&ctx0, device1);
libraryFunc();
libraryDeinitialize();// Library codelibraryInitialize() {map<CUcontext, CUmodule> moduleContextMap;
}libraryFunc() {cuCtxGetCurrent(&ctx);if (!moduleContextMap.contains(ctx)){cuModuleLoad(&module, “myModule.cubin”);moduleContextMap[ctx] = module;}else {module = moduleContextMap[ctx];}cuModuleGetFuntion(&function, module, “myKernel”);cuLaunchKernel(function,);
}libraryDeinitialize() {moduleContextMap.clear();
}

在代码示例中,库必须检查新上下文并将模块显式加载到其中。 它还必须维护状态以检查模块是否已加载到上下文中。

理想情况下,状态可以在上下文被销毁后释放。 但是,如果库无法控制上下文的生命周期,这是不可能的。

这意味着资源的释放必须延迟到库取消初始化。 这不仅增加了代码的复杂性,而且还导致库占用资源的时间超过了它必须占用的时间,可能会拒绝应用程序的另一部分使用该内存。

另一种选择是让库和框架对用户施加额外的限制,以确保他们对资源分配和清理有足够的控制权。

上下文独立的加载(Context-independent loading)

CUDA 12.0 通过添加 cuLibrary* 和 cuKernel* API 引入了上下文无关加载,从而解决了这些问题。 通过上下文独立加载,在应用程序创建和销毁上下文时,CUDA 驱动程序会自动将模块加载和卸载到每个 CUDA 上下文中。

// Load library
cuLibraryLoadFromFile(&library,“myModule.cubin”, …);
cuLibraryGetKernel(&kernel, library, “myKernel”);// Launch kernel on the primary context of device 0
cuDevicePrimaryCtxRetain(&ctx0, device0);
cuLaunchKernel((CUkernel)kernel, …);// Launch kernel on the primary context of device 1
cuDevicePrimaryCtxRetain(&ctx1, device1);
cuLaunchKernel((CUkernel)kernel, …);// Unload library
cuLibraryUnload(library);

如代码示例所示,cuLibraryLoadFromFile API 负责在创建或初始化上下文时加载模块。 在示例中,这是在 cuDevicePrimaryCtxRetain 期间完成的。

此外,您现在可以使用与上下文无关的句柄 CUkernel 启动内核,而不必维护每个上下文的 CUfunction。 cuLibraryGetKernel 检索设备函数 myKernel 的上下文无关句柄。 然后可以通过指定与上下文无关的句柄 CUkernel 来使用 cuLaunchKernel 启动设备功能。 CUDA 驱动程序负责根据此时处于活动状态的上下文在适当的上下文中启动设备功能。

库和框架现在可以分别在初始化和取消初始化期间简单地加载和卸载模块一次。

// Application codelibraryInitialize();
cuDevicePrimaryCtxRetain(&ctx0, device0);
libraryFunc();
cuDevicePrimaryCtxRetain(&ctx0, device1);
libraryFunc();
libraryDeinitialize();// Library codelibraryInitialize() {cuLibraryLoadFromFile(&library,“myModule.cubin”,);cuLibraryGetKernel(&kernel, library, “myKernel”);
}libraryFunc() {cuLaunchKernel((CUkernel)kernel,);
}libraryDeinitialize() {cuLibraryUnload(library);
}

该库不再需要维护和跟踪每个上下文的状态。 context-independent loading的设计使得CUDA driver能够跟踪模块和context,进行加载和卸载模块的工作。

访问 __managed__ 变量

托管变量可以从设备和主机代码中引用。 例如,可以查询托管变量的地址,或者可以直接从设备或主机函数读取或写入它。 与具有创建它的 CUDA 上下文的生命周期的 __device__ 变量不同,属于模块的 __managed__ 变量指向跨所有 CUDA 上下文甚至设备的相同内存。

在 CUDA 12.0 之前,无法通过驱动程序 API 检索到跨 CUDA 上下文唯一的托管变量的句柄。 CUDA 12.0 引入了一个新的驱动程序 API cuLibraryGetManaged,这使得跨 CUDA 上下文获取唯一句柄成为可能。

开始使用与上下文无关的加载

在本文中,我们介绍了新的 CUDA 驱动程序 API,它们提供了独立于 CUDA 上下文加载设备代码的能力。 我们还讨论了用于启动内核的与上下文无关的句柄。 与传统的加载机制相比,它们共同提供了一种在 GPU 上加载和执行代码的更简单方法,从而降低了代码复杂性并避免了维护每个上下文状态的需要。

要开始使用这些 API,请下载 CUDA 驱动程序和工具包版本 12 或更高版本。 有关 cuLibrary* 和 cuKernel* API 的更多信息,请参阅 CUDA Driver API 文档。

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

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

相关文章

前端跨域怎么办?

如果网上搜到的方法都不可行或者比较麻烦&#xff0c;可以尝试改变浏览器的设置&#xff08;仅为临时方案&#xff09; 1.新建一个Chrome浏览器的快捷方式 2.鼠标右键&#xff0c;进入属性&#xff0c;将以下命令复制粘贴到目标位置&#xff08;可根据Chrome实际存放位置修改…

免费的 ChatGPT 网站(六个)

&#x1f525;博客主页&#xff1a; 小羊失眠啦. &#x1f3a5;系列专栏&#xff1a;《C语言》 《数据结构》 《C》 《Linux》 《Cpolar》 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 文章目录 一、insCode二、讯飞星火三、豆包四、文心一言五、通义千问六、360智脑 现在智能…

在 Ubuntu 12.10 安装 wxPython

安装 wxPython 可以使用 pip 工具&#xff0c;但在 Ubuntu 12.10 上需要首先安装 wxPython 的依赖项。请注意&#xff0c;Ubuntu 12.10 已于2013年终止支持&#xff0c;建议升级到更高版本的 Ubuntu。以下是在 Ubuntu 12.10 上安装 wxPython 的一般步骤&#xff1a; 一、问题背…

3D开发工具HOOPS:推动汽车行业CAD可视化发展

在最近的行业对话中&#xff0c;Tech Soft 3D&#xff08;HOOPS厂商&#xff09;的Jonathan Girroir和Actify的Peter West探讨了CAD可视化在当代企业中的重要性和挑战。作为CAD可视化领域的佼佼者&#xff0c;Actify通过其广受欢迎的Spinfire应用&#xff0c;赋能了全球40多个国…

吃透1250道AMC10历年真题和详细解析,科学高效备考2024年AMC10

距离2024年AMC10比赛正式开始还有6个多月的时间&#xff0c;备考要趁早。 我们今天继续来随机看5道AMC10真题&#xff0c;以及详细解析&#xff0c;这些题目来自1250道完整的官方历年AMC10真题库。 2000-2023年AMC10真题练习和解析&#xff1a;2020年第21题 这道题的考点是等比…

关于机器学习/深度学习的一些事-答知乎问(五)

嵌入学习方法在解决小样本学习问题时面临的挑战是什么&#xff1f; &#xff08;1&#xff09;过度依赖于辅助数据&#xff0c;预训练的模式违背了小样本学习的本质定义。几乎所有的嵌入学习方法都需要通过大量辅助样本来预训练特征嵌入函数&#xff0c;但在实际应用场景中&am…

大数据存储解决方案和处理流程——解读大数据架构(四)

文章目录 前言数据存储解决方案数据集市运营数据存储&#xff08;Operational Data Store&#xff09;数据中心 数据处理数据虚拟化和数据联合虚拟化作为 ETL 或数据移动的替代品数据目录数据市场 前言 在数字时代&#xff0c;数据已成为公司的命脉。但是&#xff0c;仅仅拥有…

VectorMap论文阅读

1. 摘要 自动驾驶系统需要对周围环境具有很好的理解&#xff0c;包括动态物体和静态高精度语义地图。现有方法通过离线手动标注来解决语义构图问题&#xff0c;这些方法存在严重的可扩展性问题。最近的基于学习的方法产生稠密的分割预测结果&#xff0c;这些预测不包含单个地图…

数据结构课程设计选做(三)---公共钥匙盒(线性表,栈,队列)

2.3.1 题目内容 2.3.1-A [问题描述] 有一个学校的老师共用N个教室&#xff0c;按照规定&#xff0c;所有的钥匙都必须放在公共钥匙盒里&#xff0c;老师不能带钥匙回家。每次老师上课前&#xff0c;都从公共钥匙盒里找到自己上课的教室的钥匙去开门&#xff0c;上完课后&…

TQ15EG开发板教程:在MPSOC上运行ADRV9371(vivado2018.3)

首先需要在github上下载两个文件&#xff0c;本例程用到的文件以及最终文件我都会放在网盘里面&#xff0c; 地址放在本文最后。首先在github搜索hdl选择第一个&#xff0c;如下图所示 GitHub网址&#xff1a;https://github.com/analogdevicesinc/hdl/releases 点击releases…

在CentOS7中安装MySQL

mysql软件安装包已提供文章顶部,有需要的可以自行下载,也可以参考文中的链接自行下载版本号。(如果没有请看个人资源列表) 本文主要介绍在centos7中如何安装mysql,以及安装过程中所遇到的问题进行解决。 后期通过Navicat Premium 16链接centos7的mysql数据库进行校验。 包…

C++ | Leetcode C++题解之第30题串联所有单词的子串

题目&#xff1a; 题解&#xff1a; class Solution { public:vector<int> findSubstring(string &s, vector<string> &words) {vector<int> res;int m words.size(), n words[0].size(), ls s.size();for (int i 0; i < n && i m …