CUDA-求最大值最小值atomicMaxatomicMin
作者:翟天保Steven
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处
实现原理
atomicMax和 atomicMin是 CUDA 中的原子操作,用于在并行计算中安全地更新共享变量的最大值和最小值。它们确保在多线程环境中,多个线程对同一个变量的访问不会导致数据竞争。使用 atomicMax可以在一个线程中比较当前值与新值,并在新值更大时更新,而 atomicMin则是用于比较和更新最小值。这些操作对于需要从多个线程中汇总结果的应用至关重要,能够确保最终结果的准确性。
本文将通过一个实战案例,进行atomic求最值的展示。
(注意本文案例基于OpenCV实现,因为我工作围绕各类图像展开,这样方便些,但是对CUDA而言,核心部分与OpenCV无关,可根据自身场景和数据结构进行更改。)
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// 预准备过程
void warmupCUDA();// 图像最值计算-CPU
void calcMaxMin_CPU(cv::Mat input, uchar &maxV, uchar &minV);// 图像最值计算-GPU
void calcMaxMin_GPU(cv::Mat input, uchar &maxV, uchar &minV);
ImageProcessing.cu
#include "ImageProcessing.cuh"// 预准备过程
void warmupCUDA()
{float* dummy_data;cudaMalloc((void**)&dummy_data, sizeof(float));cudaFree(dummy_data);
}// 图像最值计算-CPU
void calcMaxMin_CPU(cv::Mat input, uchar &maxV, uchar &minV)
{int row = input.rows;int col = input.cols;// 初始化最值maxV = 0;minV = 255;for (int i = 0; i < row; ++i){for (int j = 0; j < col; ++j){if (input.at<uchar>(i, j) > maxV){maxV = input.at<uchar>(i, j);}if (input.at<uchar>(i, j) < minV){minV = input.at<uchar>(i, j);}}}
}// 获取最大最小值核函数
__global__ void getMaxMinValue_CUDA(uchar* inputImage, int width, int height, int *maxV, int *minV)
{int row = blockIdx.y * blockDim.y + threadIdx.y;int col = blockIdx.x * blockDim.x + threadIdx.x;if (row < height && col < width){atomicMax(maxV, int(inputImage[row * width + col]));atomicMin(minV, int(inputImage[row * width + col]));}
}// 图像最值计算-GPU
void calcMaxMin_GPU(cv::Mat input, uchar &maxV, uchar &minV)
{int row = input.rows;int col = input.cols;// 定义计时器float spendtime = 0.0f;cudaEvent_t start, end;cudaEventCreate(&start);cudaEventCreate(&end);// 分配GPU内存 uchar* d_inputImage;cudaMalloc(&d_inputImage, row * col * sizeof(uchar));// 将输入图像数据从主机内存复制到GPU内存cudaMemcpy(d_inputImage, input.data, row * col * sizeof(uchar), cudaMemcpyHostToDevice);// 计算块和线程的大小dim3 blockSize(TILE_WIDTH, TILE_WIDTH);dim3 gridSize((col + blockSize.x - 1) / blockSize.x, (row + blockSize.y - 1) / blockSize.y);// 求最值int h_maxValue = 0;int h_minValue = 255;int *d_maxValue;int *d_minValue;cudaMalloc((void**)&d_maxValue, sizeof(int));cudaMalloc((void**)&d_minValue, sizeof(int));cudaMemcpy(d_maxValue, &h_maxValue, sizeof(int), cudaMemcpyHostToDevice);cudaMemcpy(d_minValue, &h_minValue, sizeof(int), cudaMemcpyHostToDevice);getMaxMinValue_CUDA << <gridSize, blockSize >> > (d_inputImage, col, row, d_maxValue, d_minValue);cudaMemcpy(&h_maxValue, d_maxValue, sizeof(int), cudaMemcpyDeviceToHost);cudaMemcpy(&h_minValue, d_minValue, sizeof(int), cudaMemcpyDeviceToHost);maxV = uchar(h_maxValue);minV = uchar(h_minValue);
}
main.cpp
#include "ImageProcessing.cuh"void main()
{// 预准备warmupCUDA();cout << "calcMaxMin test begin." << endl;// 加载cv::Mat src = imread("test pic/test5.jpg", 0);// 调整数据区间cv::Mat src2;cv::normalize(src, src2, 20, 230, NORM_MINMAX);// CPU版本clock_t s1, e1;s1 = clock();uchar maxV1, minV1;calcMaxMin_CPU(src2, maxV1, minV1);e1 = clock();cout << "CPU time:" << double(e1 - s1) << "ms" << endl;cout << "maxV1:" << int(maxV1) << endl;cout << "minV1:" << int(minV1) << endl;// GPU版本clock_t s2, e2;s2 = clock();uchar maxV2, minV2;calcMaxMin_GPU(src2, maxV2, minV2);e2 = clock();cout << "GPU time:" << double(e2 - s2) << "ms" << endl;cout << "maxV2:" << int(maxV2) << endl;cout << "minV2:" << int(minV2) << endl;cout << "calcMaxMin test end." << endl;}
测试效果
在本文案例中,我通过归一化函数将图像的最值设为20和230,所以验证功能是否正确,只需要判断下函数执行完输出的最值是不是20和230即可。速度方面,CUDA也是很快的,我原以为这种简单计算CPU会更有优势。
该功能相对简单,但也很常用。后续我会写一篇关于归一化的CUDA文章,归一化中很重要的一部分就是确认最值。
如果函数有什么可以改进完善的地方,非常欢迎大家指出,一同进步何乐而不为呢~
如果文章帮助到你了,可以点个赞让我知道,我会很快乐~加油!
相关文章:

CUDA-求最大值最小值atomicMaxatomicMin
作者:翟天保Steven 版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处 实现原理 atomicMax和 atomicMin是 CUDA 中的原子操作,用于在并行计算中安全地更新共享变量的最大值和最小值。它们确…...

新的Midjourney就是一个增强版的Photoshop,你现在可以轻松的用它换衣服、换发型了
好久没有聊 Midjourney 了,昨晚他们发布了一项引人注目的新功能:AI 图像编辑,一个基于网页的加强版的 Photoshop 呼之欲出,让我大为震撼,也让用户们赞叹不已。 基于现有图像进行参考,进而生成新的图片&…...
Linux系统安装软件的4种方式【源码配置编译安装、yum安装、rpm包安装、二进制软件包安装(.rpm/.tar.gz/.tgz/.bz2)】
一.源码安装 linux安装软件采用源码安装灵活自由,适用于不同的平台,维护也十分方便。 (一)源码安装流程 源码的安装一般由3个步骤组成: 1.配置(configure) Configure是一个可执行脚本…...

基于Spring Boot的洪涝灾害应急信息管理系统设计与实现
摘要 近年来,全球气候变化加剧,洪涝灾害频发,给各国的经济发展和人民生活带来了巨大的威胁。为了提高洪涝灾害的应急响应能力,开发高效的应急信息管理系统变得至关重要。本文基于Spring Boot框架,设计并实现了一个洪涝…...
912.排序数组(桶排序)
目录 题目解法 题目 给你一个整数数组 nums,请你将该数组升序排列。 你必须在 不使用任何内置函数 的情况下解决问题,时间复杂度为 O(nlog(n)),并且空间复杂度尽可能小。 解法 class Solution { public:vector<int> sortArray(vect…...

IPC 进程间通信 消息队列
操作系统内核中采用一个链式队列管理消息,每个节点就对应一个消息: 操作系统规定了单个消息的数据长度不能超过8k(8192个字节),一个消息队列的表长(节点数)最多不超过256个 利用消息队列进行通信的特点: 1. 全双工:任何参与通信的…...

opencv 图像翻转- python 实现
在做图像数据增强时会经常用到图像翻转操作 flip。 具体代码实现如下: #-*-coding:utf-8-*- # date:2021-03 # Author: DataBall - XIAN # Function: 图像翻转import cv2 # 导入OpenCV库path test.jpgimg cv2.imread(path)# 读取图片 cv2.namedWindow(image,1) …...

使用DolphinScheduler接口实现批量导入工作流并上线
使用DS接口实现批量导入工作量并上线脚本 前面实现了批量生成DS的任务,当导入时发现只能逐个导入,因此通过接口实现会更方便。 DS接口文档 DS是有接口文档的地址是 http://IP:12345/dolphinscheduler/swagger-ui/index.html?languagezh_CN&lang…...
pycharm导出环境安装包列表
pycharm导出环境安装包列表 一、导出安装包列表二、安装requirements.txt三、列表显示已安装的包四、显示特定包的信息 一、导出安装包列表 pip freeze > requirements.txt二、安装requirements.txt pip install -r requirements.txt三、列表显示已安装的包 pip list四、…...

分体式智能网关在现代电力物联网中的优势有哪些?
随着电力系统的不断数字化和智能化,电力物联网已经成为现代电力行业发展的重要方向。电力物联网通过各种智能设备和传感器实现电力系统的监测、数据采集和分析,从而优化电力资源配置,提高电网的安全性和稳定性。在这个背景下,&quo…...

第14篇:下一代网络与新兴技术
目录 引言 14.1 下一代网络(NGN)的定义与特点 14.2 IPv6协议的改进与未来应用 14.3 软件定义网络(SDN) 14.4 网络功能虚拟化(NFV) 14.5 量子通信网络 14.6 软件定义广域网(SD-WAN&#x…...

物联网数据采集网关详细介绍-天拓四方
一、物联网数据采集网关的概述 物联网数据采集网关,简称数据采集网关,是物联网系统中的重要组成部分,位于物联网设备和云端平台之间。其主要职责是实现数据的采集、汇聚、转换、传输等功能,确保来自不同物联网设备的数据能够统一…...

2024软考网络工程师笔记 - 第10章.组网技术
文章目录 交换机基础1️⃣交换机分类2️⃣其他分类方式3️⃣级联和堆叠4️⃣堆叠优劣势5️⃣交换机性能参数 🕑路由器基础1️⃣路由器接口2️⃣交换机路由器管理方式2️⃣交换机路由器管理方式 交换机基础 1️⃣交换机分类 1.根据交换方式分 存储转发式交换(Store…...
C语言——字符串指针和字符串数组
目录 前言 一、定义区别 1、数组表示 2、指针表示 二、内存管理区别 1.字符数组 2.字符指针 三、操作区别 1、访问与修改 2、遍历 3...... 总结 前言 在C语言中,字符串随处可见,字符串是由字符组成的一串数据,字符串以null字符(\0)结尾&#…...
7-1回文判断(栈和队列PTA)
回文是指正读反读均相同的字符序列,如“abba”和“abdba”均是回文,但“good”不是回文。编写一个程序,使用栈判定给定的字符序列是否为回文。 若用C,可借助STL的容器实现。 输入格式: 输入待判断的字符序列,按回车…...

使用 NCC 和 PKG 打包 Node.js 项目为可执行文件(Linux ,macOS,Windows)
🎬 江城开朗的豌豆:个人主页 🔥 个人专栏 :《 VUE 》 《 javaScript 》 📝 个人网站 :《 江城开朗的豌豆🫛 》 ⛺️ 生活的理想,就是为了理想的生活 ! 目录 📘 文章引言 步骤 1:…...
LeetCode:2747. 统计没有收到请求的服务器数目(滑动窗口 Java)
目录 2747. 统计没有收到请求的服务器数目 题目描述: 实现代码与解析: 滑动窗口 原理思路: 2747. 统计没有收到请求的服务器数目 题目描述: 给你一个整数 n ,表示服务器的总数目,再给你一个下标从 0 开…...
项目管理工具--【项目策划任务书】模板
项目策划任务书是项目管理中的重要文件,它详细描述了项目的各个方面,以确保项目能够顺利进行。撰写项目策划任务书时需要考虑以下几个关键要素: 基本信息:包括项目名称、负责人、所在单位、联系方式以及日期等基本信息,…...

雷池社区版那么火,为什么站长都使用雷池社区版??
雷池社区版是长亭科技开发的一款免费开源的 Web 应用防火墙(WAF),具有诸多优势,因此值得使用。 防护效果强大。能够检测并防御各种网络攻击,包括 SQL 注入、跨站脚本(XSS)、跨站请求伪造&#x…...
分布式日志有哪些?
分布式日志系统(Distributed Logging Systems)是在分布式计算环境中用来收集、存储和管理来自多个节点的日志数据的系统。这些系统通常设计用于处理高并发、大规模的日志数据流,并提供强大的查询和分析功能。 一、定义与背景 分布式系统通常…...

Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...

【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...

Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...

基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...

深度学习习题2
1.如果增加神经网络的宽度,精确度会增加到一个特定阈值后,便开始降低。造成这一现象的可能原因是什么? A、即使增加卷积核的数量,只有少部分的核会被用作预测 B、当卷积核数量增加时,神经网络的预测能力会降低 C、当卷…...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...