CUDA-纹理内存

作者:翟天保Steven
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处

纹理内存是什么?

       在 GPU 编程中,纹理内存是一种专门用于二维和三维数据读取的存储方式,特别适合图像处理等应用。通过使用纹理内存,开发者可以利用硬件加速的双线性插值功能,显著提高图像缩放、旋转、平滑等操作的性能。

       在这篇文章中,我们将通过一个具体的 CUDA 图像放大案例来深入理解纹理内存的使用。本文的示例展示了如何将图像加载到 GPU 的纹理内存中,利用 CUDA 的cudaTextureObject_t对象进行双线性插值,并通过 CUDA 核函数实现图像放大。我们将详细讨论以下几个要点:

  1. CUDA 纹理内存的基本概念

    • 纹理内存是一种只读内存,专门为频繁读取操作设计,可以在 GPU 上使用硬件加速的插值功能。
    • 在图像处理过程中,纹理内存允许开发者利用不同的插值模式(如最近邻和双线性插值)来提高性能和图像质量。
  2. 纹理内存的创建与使用

    • 本文示例展示了如何将输入图像转换为浮点型格式并复制到 CUDA 数组,再创建纹理对象以供内核函数使用。
    • 通过 cudaCreateTextureObject,将输入图像加载到纹理内存中,简化了图像采样位置的计算,并通过硬件加速的双线性插值提高放大效果。
  3. CUDA 核函数进行图像缩放

    • 我们通过自定义的 scaleKernel 内核函数来完成图像缩放操作,纹理对象提供的双线性插值确保了缩放后的图像质量。
    • 内核函数根据输出图像的大小计算对应的采样坐标,利用 tex2D 函数从纹理内存中获取像素值并进行插值处理。
  4. 性能提升与纹理内存的优势

    • 纹理内存提供的插值和缓存功能使得图像处理的计算性能得到显著提升,特别是在处理大规模图像时。
    • 通过 CUDA 事件计时器,我们能够精确记录内核函数的执行时间,并分析其性能优势。

       通过文章案例,你将更好地理解纹理内存的作用和使用方式,同时了解到 CUDA 在图像处理领域的强大性能提升效果。

C++代码

ImageProcessing.cuh

#pragma once
#include <cuda_runtime.h>
#include <iostream>
#include <vector>
#include <opencv2/opencv.hpp>
#include <device_launch_parameters.h>using namespace cv;
using namespace std;#define TILE_WIDTH 16// 图像放大-CPU
cv::Mat enlargeImage_CPU(cv::Mat input, float scale);// 图像放大-GPU
cv::Mat enlargeImage_GPU(cv::Mat input, float scale);

ImageProcessing.cu

#include "ImageProcessing.cuh"// 图像放大-CPU
cv::Mat enlargeImage_CPU(cv::Mat input, float scale)
{cv::Mat result;cv::resize(input, result, cv::Size(0, 0), scale, scale, INTER_LINEAR);return result;
}
// 图像比例变化核函数
__global__ void scaleKernel(cudaTextureObject_t texObj, float* output, int outWidth, int outHeight, float scaleX, float scaleY)
{int x = blockIdx.x * blockDim.x + threadIdx.x;int y = blockIdx.y * blockDim.y + threadIdx.y;if (x < outWidth && y < outHeight) {// 计算输入图像中的采样位置float u = x * scaleX;float v = y * scaleY;// 读取纹理并自动进行双线性插值float pixel = tex2D<float>(texObj, u, v);// 将缩放后的像素值写入输出output[y * outWidth + x] = pixel;}
}
// 图像放大-GPU
cv::Mat enlargeImage_GPU(cv::Mat input, float scale)
{// 定义计时器float spendtime = 0.0f;cudaEvent_t start, end;cudaEventCreate(&start);cudaEventCreate(&end);// 获取图像的宽度和高度int imgWidth = input.cols;int imgHeight = input.rows;// 将图像数据转为 float 类型cv::Mat imgFloat;input.convertTo(imgFloat, CV_32FC1);// 缩放后图像尺寸int outWidth = int(imgWidth * scale);int outHeight = int(imgHeight * scale);// 分配设备内存float* d_outputImage;cudaMalloc(&d_outputImage, outWidth * outHeight * sizeof(float));// 分配并复制输入图像到 CUDA 数组(纹理内存)cudaArray* cuArray;cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc<float>();cudaMallocArray(&cuArray, &channelDesc, imgWidth, imgHeight);cudaMemcpyToArray(cuArray, 0, 0, imgFloat.ptr<float>(), imgWidth * imgHeight * sizeof(float), cudaMemcpyHostToDevice);// 定义纹理资源描述符cudaResourceDesc resDesc;memset(&resDesc, 0, sizeof(resDesc));resDesc.resType = cudaResourceTypeArray;resDesc.res.array.array = cuArray;// 定义纹理描述符cudaTextureDesc texDesc;memset(&texDesc, 0, sizeof(texDesc));texDesc.addressMode[0] = cudaAddressModeClamp;  texDesc.addressMode[1] = cudaAddressModeClamp;texDesc.filterMode = cudaFilterModeLinear;   texDesc.readMode = cudaReadModeElementType;     texDesc.normalizedCoords = 0;                // 创建纹理对象cudaTextureObject_t texObj = 0;cudaCreateTextureObject(&texObj, &resDesc, &texDesc, nullptr);// 定义CUDA块和线程数dim3 blockDim(TILE_WIDTH, TILE_WIDTH);dim3 gridDim((outWidth + blockDim.x - 1) / blockDim.x, (outHeight + blockDim.y - 1) / blockDim.y);// 计算输出图像在源图像中的比例关系float scaleX = static_cast<float>(imgWidth) / outWidth; float scaleY = static_cast<float>(imgHeight) / outHeight;// 调用CUDA核函数执行缩放操作cudaEventRecord(start, 0);scaleKernel << <gridDim, blockDim >> > (texObj, d_outputImage, outWidth, outHeight, scaleX, scaleY);cudaDeviceSynchronize();cudaEventRecord(end, 0);cudaEventSynchronize(end);cudaEventElapsedTime(&spendtime, start, end);cout << "scaleKernel spend time:" << spendtime << "ms" << endl;// 将处理后的图像数据从GPU内存复制回主机内存cv::Mat output(outHeight, outWidth, CV_32FC1);cudaMemcpy(output.data, d_outputImage, outWidth * outHeight * sizeof(float), cudaMemcpyDeviceToHost);// 转为灰度图像并保存cv::Mat result8U;output.convertTo(result8U, CV_8UC1);// 清理资源cudaDestroyTextureObject(texObj);cudaFreeArray(cuArray);cudaFree(d_outputImage);return result8U;
}

main.cpp

#include "ImageProcessing.cuh"// 预准备过程
void warmupCUDA()
{float* dummy_data;cudaMalloc((void**)&dummy_data, sizeof(float));cudaFree(dummy_data);
}void main()
{// 预准备warmupCUDA();cout << "enlargeImage test begin." << endl;// 加载cv::Mat src = imread("test pic/test3.jpg", 0);float scale = 5.0f;cout << "scale:" << scale << endl;cout << "size: " << src.cols << " * " << src.rows << endl;// CPU版本clock_t s1, e1;s1 = clock();cv::Mat output1 = enlargeImage_CPU(src, scale);e1 = clock();cout << "CPU time:" << double(e1 - s1)<< "ms" << endl;// GPU版本clock_t s2, e2;s2 = clock();cv::Mat output2 = enlargeImage_GPU(src, scale);e2 = clock();cout << "GPU time:" << double(e2 - s2) << "ms" << endl;// 查看输出cv::Mat test1 = output1.clone();cv::Mat test2 = output2.clone();cout << "enlargeImage test end." << endl;}

测试效果 

       如上图所示,CPU和GPU版本代码均实现了图像放大,放大图像如上所示。

       在时间上,CPU看起来比GPU快,是因为GPU大多耗时集中在数据传输过程;若只关注核函数,耗时仅为0.5ms,说明纹理内存具备很强优势。

       如果函数有什么可以改进完善的地方,非常欢迎大家指出,一同进步何乐而不为呢~

       如果文章帮助到你了,可以点个赞让我知道,我会很快乐~加油!

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

[SAP ABAP] 数据字典外键关联

SE11创建自定义数据库表 学校表(ZDBT_SCH_437) 表有3个组成字段&#xff1a; ① MANDT (参考数据元素为MANDT&#xff0c;主键) ② SCHID 学校ID (参考新建数据元素ZDE_SCHID_437&#xff0c;主键&#xff0c;NUMC4) ③ SCHNAME 学校名称 (CHAR20) 学生表(ZDBT_STU_437) 表有7个…

基于微信小程序校园订餐的设计与开发+ssm(lw+演示+源码+运行)

摘 要 人民生活水平的提高就会造成生活节奏越来越快&#xff0c;很多人吃饭都采用点外卖的方式。现在点外卖的平台已有很多&#xff0c;大多都需要安装它们的APP才可以使用&#xff0c;并且没有针对校园。如果一味的使用外卖平台不仅会造成商家成本的增加&#xff0c;还不利于…

基于微信小程序的智慧物业管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏&#xff1a;Java精选实战项目…

C++容器list底层迭代器的实现逻辑~list相关函数模拟实现

目录 1.两个基本的结构体搭建 2.实现push_back函数 3.关于list现状的分析&#xff08;对于我们如何实现这个迭代器很重要&#xff09; 3.1和string,vector的比较 3.2对于list的分析 3.3总结 4.迭代器类的封装 5.list容器里面其他函数的实现 6.个人总结 7.代码附录 1.两…

easylogger移植

1.源码 GitHub - armink/EasyLogger: An ultra-lightweight(ROM<1.6K, RAM<0.3k), high-performance C/C log library. | 一款超轻量级(ROM<1.6K, RAM<0.3k)、高性能的 C/C 日志库 2.介绍 easylogger就是用来打印日志的,我们可以将日志输出到sscom, led屏幕, 或者…

多模态交互才是人机交互的未来

交互方式 在探讨文字交流、语音交流和界面交流的效率时&#xff0c;我们可以看到每种方式都有其独特的优势和局限性。文字交流便于记录和回溯&#xff0c;语音交流则在表达情绪和非语言信息方面更为高效&#xff0c;而界面交流则依赖于图形用户界面&#xff08;GUI&#xff09…

[大语言模型-论文精读] 以《黑神话:悟空》为研究案例探讨VLMs能否玩动作角色扮演游戏?

1. 论文简介 论文《Can VLMs Play Action Role-Playing Games? Take Black Myth Wukong as a Study Case》是阿里巴巴集团的Peng Chen、Pi Bu、Jun Song和Yuan Gao&#xff0c;在2024.09.19提交到arXiv上的研究论文。 论文: https://arxiv.org/abs/2409.12889代码和数据: h…

Mixamo动画使用技巧

1、登录Mixiamo网站 2、下载人物模型 3、找到FBX文件 选中人形骨骼 3、下载动画 4、拖拽FBX 5、注意事项 生成的FBX文件中会包含一个骨骼一个动画 如果人物有骨骼&#xff0c;则不需要&#xff0c;没有需要对应此包中的骨骼&#xff0c;骨骼不可以通用&#xff0c;动画通用 …

某集群管理系统存在任意文件读取漏洞

你为什么要拼命努力&#xff1f;父母的白发&#xff0c;想去的地方很远&#xff0c;想要的东西很贵&#xff0c;喜欢的人很优秀&#xff0c;周围人的嘲笑&#xff0c;以及&#xff0c;天生傲骨。 漏洞描述 利用漏洞&#xff0c;攻击者可以读取 Windows 或 Linux 服务器上的任…

【QT开发-Pyside】使用Pycharm与conda配置Pyside环境并新建工程

知识拓展 Pycharm 是一个由 JetBrains 开发的集成开发环境&#xff08;IDE&#xff09;&#xff0c;它主要用于 Python 编程语言的开发。Pycharm 提供了代码编辑、调试、版本控制、测试等多种功能&#xff0c;以提高 Python 开发者的效率。 Pycharm 与 Python 的关系 Pycharm 是…

微信小程序教程:如何在个人中心实现头像贴纸功能

在微信小程序中&#xff0c;个性化设置是提升用户体验的重要手段。本文将详细介绍如何在个人中心模块中实现头像贴纸功能&#xff0c;让用户可以自由地装饰自己的头像。 头像贴纸功能允许用户在个人头像上添加装饰性贴纸&#xff0c;增加个性化表达。以下是实现该功能的主要步骤…

安全帽佩戴识别摄像机:守护安全的智能之眼

在现代工业和建筑等诸多领域中&#xff0c;安全始终是重中之重。每一处施工现场、每一个生产车间都潜藏着可能对人员造成伤害的风险因素。而安全帽&#xff0c;作为保护工作人员头部免受伤害的关键装备&#xff0c;其是否被正确佩戴就显得尤为关键。此时&#xff0c;安全帽佩戴…

mysql数据库--索引

索引 1.索引 在数据中索引最核心的作用就是&#xff1a;加速查找 1.1 索引原理 索引的底层是基于BTree的数据存储结构 如图所示&#xff1a; 很明显&#xff0c;如果有了索引结构的查询效率比表中逐行查询的速度要快很多且数据越大越明显。 数据库的索引是基于上述BTree的…

硬件(驱动开发概念)

驱动程序开发 裸机驱动&#xff08;无操作系统&#xff09; Linux驱动 以计算机技术为基础&#xff0c;在软件和硬件层间可以被剪裁的专业硬件计算机系统 SOC&#xff1a;片上系统 Kernel&#xff1a;内核 x86 &#xff08;CISC:complex instruction set computer 复杂指令…

一款前后端分离CRM客户关系管理系统,支持客户,商机,线索,合同,发票,审核,商品等功能(附源码)

前言 在当今竞争激烈的商业环境中&#xff0c;企业面临着各种挑战&#xff0c;其中包括如何更有效地管理和跟进潜在客户以提高销售业绩。传统的客户管理方式往往效率低下&#xff0c;无法实时更新客户-信息&#xff0c;导致销售机会流失。因此&#xff0c;市场上急需一款能够简…

GitHub 上高星 AI 开源项目推荐

FIFO-Diffusion 介绍&#xff1a;FIFO-Diffusion 是一个创新的开源项目&#xff0c;它能够基于文本描述生成无限长度的高品质视频&#xff0c;而无需任何预先的模型训练。这一技术的核心在于其高效的内存管理策略和先进的扩散模型&#xff0c;使得即使是小型GPU配置也能轻松应…

ES学习笔记

目录 简介 原理 基础概念 lucene总结 es的进步 实现过程 写入流程 搜索过程 和Mysql搭配 学习来源&#xff1a;https://i12pc3nf6d.feishu.cn/wiki/FnPwwGXGli1ANGkaMz5chvhmn2e#share-OYKJdYhehotnMgxrBiUcZSJJnCb https://i12pc3nf6d.feishu.cn/wiki/FnPwwGXGli1ANG…

【Linux】【Hadoop】大数据基础实验一

实验一&#xff1a;熟悉常用的Linux操作和Hadoop操作 一、实验目的 Hadoop运行在Linux系统上&#xff0c;因此&#xff0c;需要学习实践一些常用的Linux命令。本实验旨在熟悉常用的Linux操作和Hadoop操作&#xff0c;为顺利开展后续其他实验奠定基础。 二、实验平台 操作系统…

comp 9517 Computer Vision week2

图像处理 1.空间域操作(Spatial domain operation)1.1 点(Point operation)1.2 邻域(Neighbourhood operation)空间滤波(spatial filtering)修复边界问题(fixing the border problem)通过卷积进行空间滤波(Spatial filtering by convolution)卷积特性&#xff1a;滤波器强度梯度…

Java 缓存机制与缓存失效

在分布式系统中&#xff0c;缓存 是提高系统性能、减轻数据库压力的常用技术。合理的缓存策略不仅能提升响应速度&#xff0c;还能节省资源。不过&#xff0c;缓存并不是万能的&#xff0c;缓存失效 是开发中必须考虑的问题。如果处理不好&#xff0c;可能会导致数据不一致或性…