[12] 使用 CUDA 进行图像处理

news2024/11/27 22:30:25

使用 CUDA 进行图像处理

  • 当下生活在高清摄像头的时代,这种摄像头能捕获高达1920*1920像素的高解析度画幅。想要实施的处理这么多的数据,往往需要几个TFlops地浮点处理性能,这些要求CPU也无法满足
  • 通过在代码中使用CUDA,可以利用GPU提供的强大地计算能力
  • CUDA支持多维地Grid和块,因此可以根据图像地尺寸、数据量大小,合理的分配块和线程进行图像处理
  • 简单图像处理过程地特定编程模式:
for(int i=0;i<image_height;i++)
{
    for(int j=0;j<image_width;j++)
    {
        //Pixel Processing code for pixel located at(i,j)
    }
}
  • 将像素处理映射到CUDA地一批线程上:
int i = blockidx.y * blockDim.y + threadIdx.y
int j = blockidx.x * blockDim.x + threadIdx.x

1. 在GPU上通过CUDA进行直方图统计

  • 首先介绍CPU版本的直方图统计,实现如下:
int h_a[1000] = Random values between 0 and 15

//假设图像取值范围在【0-15】,定义数组并初始化
int histogram[16];
for(int i=0;i<16;i++)
{
    histogram[i] = 0;
}
//统计每个值的个数
for(int i=0;i<1000;i++)
{
    histogram[h_a[i]]+=1;
}
  • 下面写一个同样功能的GPU代码,我们将使用3种不同的方法写这个代码,前两种方法的内核代码如下:
__global__ void histogram_without_atomic(int* d_b, int* d_a)
{
	int tid = threadIdx.x + blockDim.x * blockIdx.x;
	int item = d_a[tid];
	if (tid < SIZE)
	{
		d_b[item]++;
	}

}

__global__ void histogram_atomic(int* d_b, int* d_a)
{
	int tid = threadIdx.x + blockDim.x * blockIdx.x;
	int item = d_a[tid];
	if (tid < SIZE)
	{
		atomicAdd(&(d_b[item]), 1);
	}
}
  • 第一个函数是最简单方式实现的直方图统计,每个线程读取 1 个元素值。使用线程ID作为输入数组的索引获取该元素的数值,然后此值再将对应的d_b结果数组中的索引位置处进行 +1 操作。最后d_b数组应该包含输入数据中0-15之间每个值的频次,这种方式将得出错误的结果,因为对相同的存储器位置将有大量的线程试图同时进行不安全的修改,其运行结果如下:
    在这里插入图片描述
  • 第二个函数用原子操作实现统计,避免多线程并行时的资源占用导致的计算异常问题,其计算结果如下:
    在这里插入图片描述
  • main函数如下:
int main()
{
	//定义设备变量并分配内存
	int h_a[SIZE];
	for (int i = 0; i < SIZE; i++) {

		h_a[i] = i % NUM_BIN;
	}
	int h_b[NUM_BIN];
	for (int i = 0; i < NUM_BIN; i++) {
		h_b[i] = 0;
	}

	// 声明GPU指针变量
	int* d_a;
	int* d_b;

	// 分配GPU变量内存
	cudaMalloc((void**)&d_a, SIZE * sizeof(int));
	cudaMalloc((void**)&d_b, NUM_BIN * sizeof(int));

	// transfer the arrays to the GPU
	cudaMemcpy(d_a, h_a, SIZE * sizeof(int), cudaMemcpyHostToDevice);
	cudaMemcpy(d_b, h_b, NUM_BIN * sizeof(int), cudaMemcpyHostToDevice);

	// 进行直方图统计
	//histogram_without_atomic << <((SIZE + NUM_BIN - 1) / NUM_BIN), NUM_BIN >> > (d_b, d_a);
	histogram_atomic << <((SIZE+NUM_BIN-1) / NUM_BIN), NUM_BIN >> >(d_b, d_a);

	// copy back the sum from GPU
	cudaMemcpy(h_b, d_b, NUM_BIN * sizeof(int), cudaMemcpyDeviceToHost);
	printf("Histogram using 16 bin without shared Memory is: \n");
	for (int i = 0; i < NUM_BIN; i++) {
		printf("bin %d: count %d\n", i, h_b[i]);
	}

	// free GPU memory allocation
	cudaFree(d_a);
	cudaFree(d_b);
	return 0;
}
  • 当我们试图测量使用了原子操作的该代码的性能的时候,你会发现相比CPU的性能,对于很大规模的数组,GPU的实现更慢。这就引入了一个问题:我们真的应当使用CUDA进行直方图统计吗?如果必须能否将这个计算更快些?
  • 这两个问题的答案都是:YES 。如果我们在一个块中用共享内存进行直方图统计,最后再将每个块的部分统计结果叠加到全局内存上的最终结果上去。这样就能加速该操作。这是因为整数加法满足交换律。我需要补充的是:只有当原始数据就在GPU的显存上的时候,才应当考虑使用GPU计算,否则完全不应当 cudaMemcpy 过来再计算,因为仅 cudaMemcpy 的时间就将等于或者大于 CPU 计算的时间,用共享内存进行直方图统计的内核函数代码实现如下:
#include <stdio.h>
#include <cuda_runtime.h>

#define SIZE 1000
#define NUM_BIN 256

__global__ void histogram_shared_memory(int* d_b, int* d_a)
{
	int tid = threadIdx.x + blockDim.x * blockIdx.x;
	int offset = blockDim.x * gridDim.x;
	__shared__ int cache[256];
	cache[threadIdx.x] = 0;
	__syncthreads();

	while (tid < SIZE)
	{
		atomicAdd(&(cache[d_a[tid]]), 1);
		tid += offset;
	}
	__syncthreads();
	atomicAdd(&(d_b[threadIdx.x]), cache[threadIdx.x]);
}
  • 我们要为当前的每个块都统计一次局部结果,所以需要先将共享内存清空,然后用类似之前的方式在共享内存中进行直方图统计。这种情况下,每个块只会统计部分结果存储在各自的共享内存中,并非像以前那样直接统计为全局内存上的总体结果。
  • 本例中,块中256个线程进行共享内存上的256个元素的访问,而原本的代码则在全局内存上的16个元素位置上进行访问。因为共享内存本身要比全局内存具有更高效的并行访问性能,同时将16个统一的竞争访问的位置放宽到了每个共享内存上的256个竞争位置,这两个因素共同缩小了原子操作累计统计的时间。
  • 最终还需要进行一次原子操作,将每个块的共享内存上的部分统计结果累加到全局内存上的最终统计结果。因为整数加法满足交换律,我们不需要担心每个块执行的顺序。
  • main函数如上一个类似:
int main()
{
	// generate the input array on the host
	int h_a[SIZE];
	for (int i = 0; i < SIZE; i++) {
		//h_a[i] = bit_reverse(i, log2(SIZE));
		h_a[i] = i % NUM_BIN;
	}
	int h_b[NUM_BIN];
	for (int i = 0; i < NUM_BIN; i++) {
		h_b[i] = 0;
	}

	// declare GPU memory pointers
	int* d_a;
	int* d_b;

	// allocate GPU memory
	cudaMalloc((void**)&d_a, SIZE * sizeof(int));
	cudaMalloc((void**)&d_b, NUM_BIN * sizeof(int));

	// transfer the arrays to the GPU
	cudaMemcpy(d_a, h_a, SIZE * sizeof(int), cudaMemcpyHostToDevice);
	cudaMemcpy(d_b, h_b, NUM_BIN * sizeof(int), cudaMemcpyHostToDevice);

	// launch the kernel
	histogram_shared_memory << <SIZE / 256, 256 >> > (d_b, d_a);

	// copy back the result from GPU
	cudaMemcpy(h_b, d_b, NUM_BIN * sizeof(int), cudaMemcpyDeviceToHost);
	printf("Histogram using 16 bin is: ");
	for (int i = 0; i < NUM_BIN; i++) {
		printf("bin %d: count %d\n", i, h_b[i]);
	}

	// free GPU memory allocation
	cudaFree(d_a);
	cudaFree(d_b);

	return 0;
}
  • 执行结果:
    在这里插入图片描述

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

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

相关文章

【网络安全的神秘世界】磁盘空间告急?如何解决“no space left on device”的困扰

&#x1f31d;博客主页&#xff1a;泥菩萨 &#x1f496;专栏&#xff1a;Linux探索之旅 | 网络安全的神秘世界 | 专接本 磁盘空间告急&#xff1f;如何解决“no space left on device”的困扰 &#x1f64b;‍♂️问题描述 错误信息 "write /var/lib/docker/tmp/GetIma…

计算机组成原理-流水CPU-指令流水

一、指令流水的定义 指令流水线是计算机处理器中的一种设计&#xff0c;用于提高指令执行的效率。考虑到执行指令的每个阶段用到的硬件不同&#xff0c;它将处理指令的各个步骤分解为若干个阶段&#xff0c;并允许多个指令在同一时刻在不同的阶段执行&#xff0c;从而实现指令…

InfiniBand网络内计算架构指南

InfiniBand网络内计算知多少&#xff1f; InfiniBand在高性能计算和人工智能领域占据核心地位&#xff0c;其高速、低延迟的网络通信能力支持大规模数据传输与复杂计算。在网络内计算领域&#xff0c;InfiniBand的应用日益广泛&#xff0c;通过内部计算降低延迟&#xff0c;提升…

【霸王餐系统】搭建部署,可设置二级分销

前言&#xff1a; 霸王餐项目通常是由外卖平台或商家发起的一种营销策略&#xff0c;旨在通过提供低成本甚至免费的外卖来吸引消费者&#xff0c;从而增加销量、优化评价并扩大市场影响力。这种项目往往能够实现平台、商家、推广者和消费者四方共赢的局面。 一、项目优势 市…

GPT-4o更易越狱?北航南洋理工上万次测试详解!

GPT-4o&#xff0c;比上一代更容易遭受越狱攻击&#xff1f; 北航和南洋理工的研究人员通过上万次API查询&#xff0c;对GPT-4o的各种模态安全性进行了详细测试。 结果发现&#xff0c;GPT-4o新引入的语音模态带来了新的攻击面&#xff0c;多模态整体安全性不如GPT-4V。 GPT-4o…

海洋气象期刊 | 个人统计

写在前面 这周末两天闲着无聊&#xff0c;统计了一些zotero中自己常看的期刊数量&#xff0c;少于5篇的未进行统计 Journal of the Atmospheric Sciences - (JAS) https://www.ametsoc.org/index.cfm/ams/publications/journals/journal-of-the-atmospheric-sciences/ 73篇 …

用教育邮箱在官网安装origin2024中文版教程

打开origin官网&#xff0c;点击learning Edition&#xff0c;教育版只能维持六个月&#xff0c;但是过期之后可以在官网更新&#xff0c;能够免费使用六次&#xff0c;也就是三年。 OriginLab - Origin and OriginPro - Data Analysis and Graphing Software 填写学校信息&…

鸿蒙开发文件管理:【@ohos.statfs (statfs)】

statfs 该模块提供文件系统相关存储信息的功能&#xff0c;向应用程序提供获取文件系统总字节数、空闲字节数的JS接口。 说明&#xff1a; 本模块首批接口从API version 8开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 导入模块 import stat…

技术干货分享:初识分布式版本控制系统Git

初识Git版本控制 自动化测试代码反复执行&#xff0c;如果借用持续集成工具会提高测试效率&#xff0c;那么需要我们把自动化测试代码发布到正式环境中&#xff0c;这时候用Git版本控制工具高效、稳定、便捷。 分布式版本控制 Git可以把代码仓库完整地镜像下来&#xff0c;有…

每日一练——有效的括号

20. 有效的括号 - 力扣&#xff08;LeetCode&#xff09; 错误记录 #include<stddef.h> #include<stdlib.h> #include<assert.h> #include<stdbool.h>typedef char STDataType;typedef struct Stack {STDataType* a;int capacity;int top; } Stack;vo…

Unity 实现WebSocket 简单通信——客户端

创建连接 ClientWebSocket socket new ClientWebSocket(); string url $"ws://{ip}:{port}"; bool createUri Uri.TryCreate(url, UriKind.RelativeOrAbsolute, out Uri uri); if (createUri) {var task socket.ConnectAsync(uri, CancellationToken.None);task…

Nginx学习笔记(九)location转发后,proxy_pass结尾带 / 和不带 / 的区别

目录 一、知识回顾二、proxy_pass 结尾带 / 和不带 / 的区别2.1 场景假设2.2 实战验证验证1&#xff1a;结尾带/的场景验证2&#xff1a;不带/的场景 2.3 结论 一、知识回顾 之前使用过 Nginx 的小伙伴或许都了解&#xff0c;Nginx 是一款用于请求转发的高性能中间件&#xff…

C++|哈希应用->位图

目录 一、概念 1.1原理分析&#xff1a; 1.2效率分析&#xff1a; 二、模拟实现 2.1位图框架初始化空间 2.2映射 2.3清零 2.4判断 2.5测试代码 三、位图扩展应用 一、概念 位图&#xff0c;本质上也是一个数组&#xff0c;通过哈希思想构造的一种数据结构&#xff0c…

unity开发Hololens编辑器运行 按空格没有手

选择DictationMixedRealityInputSystemProfile 如果自定义配置文件 需要可能需要手动设置 手部模型和材质球

SQL 窗口函数

1.窗口函数之排序函数 RANK, DENSE_RANK, ROW_NUMBER RANK函数 计算排序时,如果存在相同位次的记录,则会跳过之后的位次 有 3 条记录排在第 1 位时: 1 位、1 位、1 位、4 位…DENSE_RANK函数 同样是计算排序,即使存在相同位次的记录,也不会跳过之后的位次 有 3 条记录排在…

Springboot高校实训管理平台-计算机毕业设计源码01557

目 录 摘要 1 绪论 1.1 研究背景 1.2 研究意义 1.3论文结构与章节安排 2 高校实训管理平台系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1 数据增加流程 2.2.2 数据修改流程 2.2.3 数据删除流程 2.3 系统功能分析 2.3.1 功能性分析 2.3.2 非功能性分析 2.4 系…

delmia中机器人末端固定工具

1 需要在工具上面建立点 在Device Building模式下 2 然后通过 set tool可以设置

247 H指数

法一&#xff1a; 不进行排序&#xff0c;直接依照原数组进行解&#xff0c;先假设h为1&#xff0c;然后找引用超过1篇的论文数量&#xff0c;如果满足&#xff0c;则再假设h为2。这样比较慢&#xff0c;时间复杂度为o(n方)。 int hIndex(vector<int>& citations) {…

天润融通引领AI大模型应用,助力企业客户感知升级

AI大模型&#xff0c;如何进行应用落地&#xff1f; 2024年&#xff0c;大模型的应用落地成为行业发展的一个重要主题&#xff0c;如何将大模型的能力与业务场景相结合&#xff0c;为企业提高效率&#xff0c;创造价值&#xff0c;成为各大企业积极探索的方向。 客户联络也是…

计算机网络:网络层 - IPv4数据报 ICMP协议

计算机网络&#xff1a;网络层 - IPv4数据报 & ICMP协议 IPv4数据报[版本 : 首部长度 : 区分服务 : 总长度][标识 : 标志 : 片偏移][生存时间 : 协议 : 首部检验和][可变部分 : 填充字段] ICMP协议 IPv4数据报 一个IPv4数据报&#xff0c;由首部和数据两部分组成&#xff…