使用 Vulkan VkImage 作为 CUDA cuArray
使用 Vulkan VkImage 作为 CUDA cuArray
【问题标题】:Use Vulkan VkImage as a CUDA cuArray使用 Vulkan VkImage 作为 CUDA cuArray
【发布时间】:2019-08-20 20:01:10
【问题描述】:
将 Vulkan VkImage 用作 CUDA cuArray 的正确方法是什么?
我一直在尝试遵循一些示例,但是我在调用 cuExternalMemoryGetMappedMipmappedArray() 时收到了 CUDA_ERROR_INVALID_VALUE
以有序的方式提供信息。
我正在使用 CUDA 10.1
基本代码来自https://github.com/SaschaWillems/Vulkan,特别是我正在使用01 - Vulkan Gears 演示,丰富了saveScreenshot 方法09 - Capturing screenshots
我不会将快照图像保存到文件中,而是将快照图像作为 CUarray 发送到 CUDA。
我已启用以下实例和设备扩展:
std::vector<const char*> instanceExtensions = {VK_EXT_DEBUG_REPORT_EXTENSION_NAME,VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME };std::vector<const char*> deviceExtensions = { VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME,VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME };
我有一个VkImage,创建如下:
// Create the linear tiled destination image to copy to and to read the memory fromVkImageCreateInfo imageCreateCI(vks::initializers::imageCreateInfo());imageCreateCI.imageType = VK_IMAGE_TYPE_2D;// Note that vkCmdBlitImage (if supported) will also do format conversions if the swapchain color format would differimageCreateCI.format = VK_FORMAT_R8G8B8A8_UNORM;imageCreateCI.extent.width = width;imageCreateCI.extent.height = height;imageCreateCI.extent.depth = 1;imageCreateCI.arrayLayers = 1;imageCreateCI.mipLevels = 1;imageCreateCI.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;imageCreateCI.samples = VK_SAMPLE_COUNT_1_BIT;imageCreateCI.tiling = VK_IMAGE_TILING_LINEAR;imageCreateCI.sharingMode = VK_SHARING_MODE_EXCLUSIVE;imageCreateCI.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;VkExternalMemoryImageCreateInfoKHR extImageCreateInfo = {};/** Indicate that the memory backing this image will be exported in an* fd. In some implementations, this may affect the call to* GetImageMemoryRequirements() with this image.*/extImageCreateInfo.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR;extImageCreateInfo.handleTypes |= VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;imageCreateCI.pNext = &extImageCreateInfo;// Create the imageVkImage dstImage;VK_CHECK_RESULT(vkCreateImage(device, &imageCreateCI, nullptr, &dstImage));// Create memory to back up the imageVkMemoryRequirements memRequirements;VkMemoryAllocateInfo memAllocInfo(vks::initializers::memoryAllocateInfo());VkDeviceMemory dstImageMemory;vkGetImageMemoryRequirements(device, dstImage, &memRequirements);memAllocInfo.allocationSize = memRequirements.size;// Memory must be host visible to copy frommemAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);VkExportMemoryAllocateInfoKHR exportInfo = {};exportInfo.sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR;exportInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;memAllocInfo.pNext = &exportInfo;VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &dstImageMemory));VK_CHECK_RESULT(vkBindImageMemory(device, dstImage, dstImageMemory, 0));从那里我会:
获取 Vulkan 内存处理程序:
intCuEncoderImpl::getVulkanMemoryHandle(VkDevice device,VkDeviceMemory memory) {// Get handle to memory of the VkImageint fd = -1;VkMemoryGetFdInfoKHR fdInfo = { };fdInfo.sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR;fdInfo.memory = memory;fdInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;auto func = (PFN_vkGetMemoryFdKHR) vkGetDeviceProcAddr(device,"vkGetMemoryFdKHR");if (!func) {printf("Failed to locate function vkGetMemoryFdKHR\n");return -1;}VkResult r = func(device, &fdInfo, &fd);if (r != VK_SUCCESS) {printf("Failed executing vkGetMemoryFdKHR [%d]\n", r);return -1;}return fd;}导入内存:
CUDA_EXTERNAL_MEMORY_HANDLE_DESC memDesc = { };memDesc.type = CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD;memDesc.handle.fd = getVulkanMemoryHandle(device, memory);memDesc.size = extent.width*extent.height*4;CUDA_DRVAPI_CALL(cuImportExternalMemory(&externalMem, &memDesc));并映射内存:这是失败的步骤。
CUarray CuEncoderImpl::getCUDAArrayFromExternalMemory(const VkExtent3D &extent,const CUexternalMemory &m_extMem) {CUmipmappedArray m_mipmapArray;CUresult result = CUDA_SUCCESS;CUarray array;CUDA_ARRAY3D_DESCRIPTOR arrayDesc = { };arrayDesc.Width = extent.width;arrayDesc.Height = extent.height;arrayDesc.Depth = 0;arrayDesc.Format = CU_AD_FORMAT_UNSIGNED_INT32;arrayDesc.NumChannels = 4;arrayDesc.Flags = CUDA_ARRAY3D_SURFACE_LDST;CUDA_EXTERNAL_MEMORY_MIPMAPPED_ARRAY_DESC mipmapArrayDesc = { };mipmapArrayDesc.arrayDesc = arrayDesc;mipmapArrayDesc.numLevels = 1;mipmapArrayDesc.offset = 0;CUDA_DRVAPI_CALL(cuExternalMemoryGetMappedMipmappedArray(&m_mipmapArray, m_extMem, &mipmapArrayDesc));CUDA_DRVAPI_CALL(cuMipmappedArrayGetLevel(&array, m_mipmapArray, 0));return array;
}我一直在尝试多种参数组合,但到目前为止都失败了。错误指向一个无效的参数,但我不知道如何找出问题所在。
唯一可行的方法是将 Vulkan 映像内存映射到主机缓冲区,然后将其复制到 CUDA 数组中......但我想这很昂贵,如果可能的话我想避免它。
【问题讨论】:
@talonmies Vulkan-CUDA 互操作性是 CUDA 10 的一项功能,请参阅 devblogs.nvidia.com/cuda-10-features-revealed
标签: cuda gpu nvidia vulkan cuda-arrays
【解决方案1】:
为了记录,我终于让它工作了。
我必须对问题中列出的代码进行一些注释和修改:
Vulkan-CUDA 互操作性被宣传为 CUDA 10 的一项功能,请参阅CUDA 10 Features revealed
要映射的图像的平铺必须是 `VK_IMAGE_TILING_OPTIMAL
imageCreateCI.tiling = VK_IMAGE_TILING_OPTIMAL;该图像的内存必须使用VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT 分配
memAllocInfo.memoryTypeIndex = vulkanDevice->getMemoryType(memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);导入内存时的内存描述符应使用内存要求中返回的内存大小(下面的size 是创建图像的代码中的memRequirements.size):
CUDA_EXTERNAL_MEMORY_HANDLE_DESC memDesc = { };memDesc.type = CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD;memDesc.handle.fd = getVulkanMemoryHandle(device, memory);memDesc.size = size;CUDA_DRVAPI_CALL(cuImportExternalMemory(&externalMem, &memDesc));最后映射的数组被描述为CU_AD_FORMAT_UNSIGNED_INT8,有四个通道和CUDA_ARRAY3D_COLOR_ATTACHMENT
CUDA_ARRAY3D_DESCRIPTOR arrayDesc = { };arrayDesc.Width = extent.width;arrayDesc.Height = extent.height;arrayDesc.Depth = 0;arrayDesc.Format = CU_AD_FORMAT_UNSIGNED_INT8;arrayDesc.NumChannels = 4;arrayDesc.Flags = CUDA_ARRAY3D_COLOR_ATTACHMENT;CUDA_EXTERNAL_MEMORY_MIPMAPPED_ARRAY_DESC mipmapArrayDesc = { };mipmapArrayDesc.arrayDesc = arrayDesc;mipmapArrayDesc.numLevels = 1;mipmapArrayDesc.offset = 0;CUDA_DRVAPI_CALL(cuExternalMemoryGetMappedMipmappedArray(&m_mipmapArray, m_extMem, &mipmapArrayDesc));
复制在这些更改之后,我能够让它工作。 我很少有更改是我这边明显的错误(比如大小),我在第 100 次仔细阅读文档时发现的一些东西,其他人是对文档中提示的猜测,最后,大量的试验和错误.
【讨论】:
非常感谢你,我设法在不到一天的时间内运行了它:)
不过,我不确定一件事。我们必须在这个管道中调用哪些销毁/释放函数?我猜,cudaFreeMipmappedArray 和 cudaDestroyExternalMemory,但不是 mipmap 级别的 cudaFreeArray?
CUDA 10 功能揭晓:图灵、CUDA 图等 |英伟达技术博客 (nvidia.com)
CUDA Toolkit 12.1 Downloads | NVIDIA Developer
NVIDIA/cuda-samples: Samples for CUDA Developers which demonstrates features in CUDA Toolkit (github.com)
相关文章:
使用 Vulkan VkImage 作为 CUDA cuArray
使用 Vulkan VkImage 作为 CUDA cuArray【问题标题】:Use Vulkan VkImage as a CUDA cuArray使用 Vulkan VkImage 作为 CUDA cuArray【发布时间】:2019-08-20 20:01:10【问题描述】:将 Vulkan VkImage 用作 CUDA cuArray 的正确方法是什么&am…...
电商API接口-电商OMS不可或缺的一块 调用代码展示
电商后台管理系统关键的一环就是实现电商平台数据的抓取,以及上下架商品、订单修改等功能的调用。这里就需要调用电商API接口。接入电商API接口后再根据自我的需求进行功能再开发,实现业务上的数字化管理。其中订单管理模板上需要用到如下API:seller_ord…...
Solaris ZFS文件系统rpool扩容
ZFS文件系统简介 Solaris10默认的文件系统是ufs(Unix Filesystem),当然也可以选装zfs;Solaris11默认的文件系统是zfs(Zettabyte Filesystem)。 ZFS文件系统的英文名称为Zettabyte File System,也叫动态文件…...
模式识别 —— 第二章 参数估计
模式识别 —— 第二章 参数估计 文章目录模式识别 —— 第二章 参数估计最大似然估计(MLE)最大后验概率估计(MAP)贝叶斯估计最大似然估计(MLE) 在语言上: 似然(likelihood…...
判断4位回文数-课后程序(Python程序开发案例教程-黑马程序员编著-第3章-课后作业)
实例1:判断4位回文数 所谓回文数,就是各位数字从高位到低位正序排列和从低位到高位逆序排列都是同一数值的数,例如,数字1221按正序和逆序排列都为1221,因此1221就是一个回文数;而1234的各位按倒序排列是43…...
【NLP】Word2Vec 介绍
Word2Vec 是一种非常流行的自然语言处理技术,它将每个单词表示为高维向量,并且通过向量之间的相似度来表示单词之间的语义关系。 1 One-Hot 编码🍂 在自然语言处理任务中,我们需要将文本转换为计算机可以理解的形式,即…...
3月6日,30秒知全网,精选7个热点
///石家庄地铁:在指定店铺购物金额不限 就可免费乘地铁 乘客只要在指定商铺或地铁站内36524便利店购物,便能得到一张当日乘车券,可免费乘坐地铁一次,不限里程 ///神州泰岳:公司语音机器人等产品能够进行多轮问答 公司…...
Python笔记 -- 字典
文章目录1、概述2、增删改查3、遍历3.1、遍历所有键值对3.2、分别遍历键和值4、嵌套4.1、字典列表4.2、在字典中储存列表4.3、在字典中储存字典1、概述 字典是一系列键值对,可将任何Python对象作为字典中的值 字典和列表容易混淆,列表也可用{} 字典是一…...
【独家】华为OD机试 - 滑动窗口(C 语言解题)
最近更新的博客 华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南)华为od机试,独家整理 已参加机试人员的实战技巧文章目录 最近更新的博客使用说明本期…...
MySQL调优 - SQL查询深度分页问题
一、问题引入 例如当前存在一张表test_user,然后往这个表里面插入3百万的数据: CREATE TABLE test_user (id int(11) NOT NULL AUTO_INCREMENT COMMENT 主键id,user_id varchar(36) NOT NULL COMMENT 用户id,user_name varchar(30) NOT NULL COMMENT 用…...
0306spring--复习
一,spring是什么 Spring是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的容器框架 理念:使现有的技术更加容易使用,本身是一个大杂烩,整合了现有的技术框架 优点࿱…...
动手实现一遍Transformer
最近乘着ChatGpt的东风,关于NLP的研究又一次被推上了风口浪尖。在现阶段的NLP的里程碑中,无论如何无法绕过Transformer。《Attention is all you need》成了每个NLP入门者的必读论文。惭愧的是,我虽然使用过很多基于Transformer的模型&#x…...
【Flutter入门到进阶】Flutter基础篇---弹窗Dialog
1 AlertDialog 1.1 说明 最简单的方案是利用AlertDialog组件构建一个弹框 1.2 示例 void alertDialog(BuildContext context) async {var result await showDialog(barrierDismissible: false, //表示点击灰色背景的时候是否消失弹出框context: context,builder: (context)…...
【操作系统】进程和线程的区别
文章目录1. 概述2. 进程3. 线程4. 协程5. 进程与线程区别1. 概述 进程和线程这两个名词天天听,但是对于它们的含义和关系其实还有点懵的,其实除了进程和线程,还存在一个协程,它们的关系如下: 首先,我们需要…...
Linux开发环境配置--正点原子阿尔法开发板
Linux开发环境配置–正点原子阿尔法开发板 文章目录Linux开发环境配置--正点原子阿尔法开发板1.网络环境设置1.1添加网络适配器1.2虚拟网络编辑器设置1.3Ubuntu和Windows网络信息设置Ubuntu网络信息配置方式:1.系统设置->网络->选项2.配置网络文件2源码准备2.…...
Android ThreadPoolExecutor的基本使用
ThreadPoolExecutor是Java中的一个线程池类,Android中也可以使用该类来管理自己的线程池,它为我们管理线程提供了很多方便。 线程池是一种能够帮助我们管理和复用线程的机制,它可以有效地降低线程创建和销毁的开销。使用线程池可以避免不必要…...
基于区域生长和形态学处理的图像融合方法——Matlab图像处理
✅ 大三下时弄的 文章目录最终效果图摘要1 研究背景及意义2 基本原理描述3 实验数据来源3.1 原始图像的来源3.2 天空背景图像的来源4 实验步骤及相应处理结果4.1 原始图像的预处理4.2 区域生长法分割图像4.3 形态学处理填充孔洞4.4 边缘检测根据二值图像构造RGB图像4.5 图像拼接…...
三个案例场景带你掌握Cisco交换机VLAN互通
VLAN间路由的方式现在主流的组网主要是依靠三层交换机通过配置SVI接口【有的厂商叫VLANIF接口】,当然也有比较小型的网络,它就一个出口路由器可管理的二层交换机,还有一种更加差的,就是出口路由一个可管理的二层交换机,…...
小白入门之持久连接与非持久连接的差别
对比 HTTP 0.9 已过时 HTTP1.0:非持续连接,每个连接只处理一个请求响应事务,有些服务器端甚至还在用此,可以在一定时间内复用连接,具体复用时间的长短可以由服务器控制,一般在15s左右。 HTTP 1.1 默认使用持…...
TypeScript篇.01-简介,类,接口,基础类型
1.简介(1)安装及编译安装: npm install -g typescript创建 .ts 后缀名的文件编译: tsc 文件名.ts 编译后会生成同名 .js 的文件查看: 在html文件中script引入js文件,运行查看控制台即可(2)类型注解TypeScript里的类型注解是一种轻量级的为函数或变量添加约束的方式 变量或函数声…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...
蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...
OkHttp 中实现断点续传 demo
在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...
如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
Linux离线(zip方式)安装docker
目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1:修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本:CentOS 7 64位 内核版本:3.10.0 相关命令: uname -rcat /etc/os-rele…...
JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...
在树莓派上添加音频输入设备的几种方法
在树莓派上添加音频输入设备可以通过以下步骤完成,具体方法取决于设备类型(如USB麦克风、3.5mm接口麦克风或HDMI音频输入)。以下是详细指南: 1. 连接音频输入设备 USB麦克风/声卡:直接插入树莓派的USB接口。3.5mm麦克…...
