gpu cuda 数组求和优化

news2024/12/28 9:23:23

欢迎关注更多精彩
关注我,学习常用算法与数据结构,一题多解,降维打击。

问题描述

给定1个数组,利用gpu求和并返回结果。

cpu 算法


#include <math.h>
#include<vector>
#include<time.h>
#include <stdio.h>

using namespace std;

#define BLOCK_SIZE 1024
#define N (102300 * 1024)

int arr[N];

void cpu_sum(int *in, int&out) {
	out = 0;
	for (int i = 0; i < N; ++i) {
		out += in[i];
	}
}


int main()
{
	float time_cpu, time_gpu;
	for (int y = 0; y < N; ++y) {
		arr[y] = y;
	}

	int cpu_result = 0;
	auto b = clock();
	cpu_sum(arr, cpu_result);
	time_cpu = clock() - b;

	printf("CPU result: %d, CPU time: %.3f\n", cpu_result, time_cpu);

	return 0;
}

cpu耗时

请添加图片描述
耗时20毫秒

gpu 算法

算法过程

  1. 先对数据分成1024*1024组,每组用1个线程进行汇总。
  2. 再把线程分成1024组,每组1024个,组内用共享内存进行快速求和。
  3. 将每组结果汇总。

共享内存求和过程:
在这里插入图片描述
设数组A为共享内存,共享内存有大小限制,一共1024个元素。
每次由前一半的线程进行操作。
第1次由前512个线程进行求和,结果放入前512个元素中。
第2次再缩减一半,直到剩下1个元素。

 for(int s = 1024/2;s;s>>=1) { // s代表当前多个线程有计算作用
 	if(tid<s)// tid代表当前线程号
 	    A[tid]+=A[tid+s];
 }

代码


#include "cuda_runtime.h"
#include<vector>
#include "device_launch_parameters.h"

#include <stdio.h>

using namespace std;

cudaError_t addWithCuda(vector<int> &a, vector<int> &sum);

__global__ void addKernel(int *dev_a, int *dev_out)
{
	int myId = threadIdx.x + blockDim.x*blockIdx.x;
	atomicAdd(dev_out, dev_a[myId]);
}

__global__ void addKernel_sheard(int *dev_a, int *dev_out, int len)
{
	extern __shared__ int sdata[];
	int myId = threadIdx.x + blockDim.x*blockIdx.x;
	int tid = threadIdx.x;

	sdata[tid] = 0;
	for (myId; myId < len; myId += blockDim.x*gridDim.x) sdata[tid] += dev_a[myId];
	__syncthreads();

	for (unsigned int s = blockDim.x / 2; s > 0; s >>= 1) {
		if (tid < s) {
			sdata[tid] += sdata[tid + s];
		}
		__syncthreads();
	}

	if (tid == 0) {
		atomicAdd(dev_out, sdata[0]);
	}
}

int main()
{
	vector<int> a(102300 * 1024);
	vector<int> sum(1024, 0);
	int s = 0;
	for (int i = 0; i < 102300 * 1024; ++i)
	{
		s += i;
		a[i] = i;
	}

	fprintf(stderr, "%d\n", s);

	// Add vectors in parallel.
	cudaError_t cudaStatus = addWithCuda(a, sum);
	if (cudaStatus != cudaSuccess) {
		fprintf(stderr, "addWithCuda failed!");
		return 1;
	}

	cudaStatus = cudaDeviceReset();
	if (cudaStatus != cudaSuccess) {
		fprintf(stderr, "cudaDeviceReset failed!");
		return 1;
	}

	s = 0;
	for (auto n : sum)s += n;
	fprintf(stderr, "%d\n", s);

	return 0;
}

// Helper function for using CUDA to add vectors in parallel.
cudaError_t addWithCuda(vector<int> &a, vector<int> &sum)
{
	int *dev_a = 0;
	int *dev_out = 0;
	cudaError_t cudaStatus;

	// Choose which GPU to run on, change this on a multi-GPU system.
	cudaStatus = cudaSetDevice(0);
	if (cudaStatus != cudaSuccess) {
		fprintf(stderr, "cudaSetDevice failed!  Do you have a CUDA-capable GPU installed?");
		goto Error;
	}

	// Allocate GPU buffers for three vectors (two input, one output)    .
	cudaStatus = cudaMalloc((void**)&dev_a, a.size() * sizeof(int));
	if (cudaStatus != cudaSuccess) {
		fprintf(stderr, "cudaMalloc failed!");
		goto Error;
	}

	cudaStatus = cudaMalloc((void**)&dev_out, sum.size() * sizeof(int));
	if (cudaStatus != cudaSuccess) {
		fprintf(stderr, "cudaMalloc failed!");
		goto Error;
	}


	// Copy input vectors from host memory to GPU buffers.
	cudaStatus = cudaMemcpy(dev_a, a.data(), a.size() * sizeof(int), cudaMemcpyHostToDevice);
	if (cudaStatus != cudaSuccess) {
		fprintf(stderr, "cudaMemcpy failed!");
		goto Error;
	}

	cudaStatus = cudaMemcpy(dev_out, sum.data(), sum.size() * sizeof(int), cudaMemcpyHostToDevice);
	if (cudaStatus != cudaSuccess) {
		fprintf(stderr, "cudaMemcpy failed!");
		goto Error;
	}

	// Launch a kernel on the GPU with one thread for each element.
	for (int i = 0; i < 1; ++i)addKernel_sheard << <1024, 1024, 1024 * sizeof(int) >> > (dev_a, dev_out, a.size());

	// Check for any errors launching the kernel
	cudaStatus = cudaGetLastError();
	if (cudaStatus != cudaSuccess) {
		fprintf(stderr, "addKernel launch failed: %s\n", cudaGetErrorString(cudaStatus));
		goto Error;
	}

	// cudaDeviceSynchronize waits for the kernel to finish, and returns
	// any errors encountered during the launch.
	cudaStatus = cudaDeviceSynchronize();
	if (cudaStatus != cudaSuccess) {
		fprintf(stderr, "cudaDeviceSynchronize returned error code %d after launching addKernel!\n", cudaStatus);
		goto Error;
	}

	// Copy output vector from GPU buffer to host memory.
	cudaStatus = cudaMemcpy(sum.data(), dev_out, sum.size() * sizeof(int), cudaMemcpyDeviceToHost);
	if (cudaStatus != cudaSuccess) {
		fprintf(stderr, "cudaMemcpy failed!");
		goto Error;
	}

Error:
	cudaFree(dev_a);
	cudaFree(dev_out);

	return cudaStatus;
}


耗时分析

请添加图片描述
耗时1.4毫秒,提升了10多倍。


本人码农,希望通过自己的分享,让大家更容易学懂计算机知识。创作不易,帮忙点击公众号的链接。

在这里插入图片描述

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

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

相关文章

了解:iperf网络性能测试工具

当进行网络性能测试时&#xff0c;可以使用iperf这个开源工具。iperf是一款网络测试工具&#xff0c;它能够测试TCP或UDP带宽质量&#xff0c;以及单向和双向吞吐量。使用iperf进行网络性能测试首先需要在被测试的两台计算机上安装iperf。 如何安装iperf&#xff1f; 在Debia…

HTTP请求行详解

目录 一、认识URL 二、认识方法 2.1 GET方法 2.2 POST方法 2.3 其他方法 请求行也就是HTTP请求的第一行&#xff0c;接下来将对第一行内容进行详细解释 一、认识URL 平时我们俗称的 "网址" 其实就是说的 URL (Uniform Resource Locator 统一资源定位符)。互联网上的…

利用哈希表封装unordered_map和unordered_set

目录 一、迭代器1.1 普通迭代器1.1.1 operator 1.2 const迭代器1.3 代码实现 二、封装unordered_set三、封装unordered_map 一、迭代器 1.1 普通迭代器 1.1.1 operator 对于哈希桶结构&#xff0c;它的迭代器应该如何设计呢&#xff1f;我们仅封装一个Node的指针就行了吗&am…

扬帆配资:首个国家层面电力现货市场 建设规则出炉

9月18日&#xff0c;国家发改委、国家动力局发布了已于近日印发的《电力现货商场底子规则&#xff08;试行&#xff09;》&#xff08;下称《规则》&#xff09;&#xff0c;作为国家层面的首个电力现货商场制作规则文件&#xff0c;推进构建全国一致电力商场系统。 扬帆配资&…

VB过程的递归调用,辗转相除法求最大公约数

VB过程的递归调用&#xff0c;辗转相除法求最大公约数 过程的递归调用&#xff0c;辗转相除法求最大公约数 Private Function gys(ByVal m%, ByVal n%) As IntegerDim r%r m Mod n m大或者n大都无所谓&#xff0c;这个不影响计算&#xff0c;由于辗转相除法的算法&#xff0c…

高阶数据结构——图

图 图的基本概念 图的基本概念 图是由顶点集合和边的集合组成的一种数据结构&#xff0c;记作 G ( V , E ) G(V, E)G(V,E) 。 有向图和无向图&#xff1a; 在有向图中&#xff0c;顶点对 < x , y >是有序的&#xff0c;顶点对 < x , y > 称为顶点 x 到顶点 y 的…

Weblogic反序列化漏洞(CVE-2018-2628/CVE-2023-21839复现)

内容目录 Weblogic反序列化漏洞(CVE-2018-2628/CVE-2023-21839)weblogic中间件CVE-2018-2628漏洞描述影响版本漏洞复现修复方案 CVE-2023-21839漏洞描述影响版本漏洞复现修复方案 Weblogic反序列化漏洞(CVE-2018-2628/CVE-2023-21839) weblogic中间件 WebLogic是美国Oracle公司…

Day 00 python基础认识与软件安装

1、基础认识 首先&#xff0c;我们先来区分、了解一些知识点 编程&#xff0c;编程语言 编程&#xff1a;用代码写一个程序 编程语言&#xff1a;用那种语法规则编写程序 &#xff08;人与计算机之间进行交流的工具&#xff1a;c、c、java、python、php、go……&am…

win系统环境搭建(四)——Windows安装mysql8压缩包版本

windows环境搭建专栏&#x1f517;点击跳转 win系统环境搭建&#xff08;四&#xff09;——Windows安装mysql8压缩包版本 本系列windows环境搭建开始讲解如何给win系统搭建环境&#xff0c;本人所用系统是腾讯云服务器的Windows Server 2022&#xff0c;你可以理解成就是你用…

openGauss学习笔记-74 openGauss 数据库管理-创建和管理视图

文章目录 openGauss学习笔记-74 openGauss 数据库管理-创建和管理视图74.1 背景信息74.2 管理视图74.2.1 创建视图74.2.2 查询视图74.2.3 查看某视图的具体信息74.2.4 删除视图 openGauss学习笔记-74 openGauss 数据库管理-创建和管理视图 74.1 背景信息 当用户对数据库中的一…

64位Ubuntu20.04.5 LTS系统安装32位运行库

背景&#xff1a; 在ubutu&#xff08;版本为20.04.5 LTS&#xff09;中运行./arm-none-linux-gnueabi-gcc -v 后提示“no such device”。 经多方查证&#xff0c;是ubutu的版本是64位的&#xff0c;而需要运行的编译工具链是32位的&#xff0c;因此会不兼容。 解决方法就是在…

ScheduledThreadPoolExecutor源码分析-延时线程池是如何实现延时执行的

ScheduledThreadPoolExecutor 线程池可以实现任务延时执行&#xff0c;那么它是怎么实现的呢&#xff1f;下面笔者进行详细分析 先看看它是怎么使用的 目录 1、延时执行使用 2、源码分析 2.1、ScheduledThreadPoolExecutor 初始化分析 2.2、ScheduledThreadPoolExecutor 执…

java项目之咖啡馆管理系统ssm+jsp

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于ssm的咖啡馆管理系统。技术交流和部署相关看文章末尾&#xff01; 开发环境&#xff1a; 后端&#xff1a; 开发语言&#xff1a;Java 框架&am…

Netty2

文章目录 Netty2Netty入站与出站机制Netty的handler链的调用机制 Netty2 Netty入站与出站机制 基本说明&#xff1a; 1&#xff09;netty的组件设计&#xff1a;Netty的主要组件有Channel&#xff0c;EventLoop&#xff0c;ChannelFuture&#xff0c;ChannelHandler&#xff…

[golang gui]fyne框架代码示例

1、下载GO Go语言中文网 golang安装包 - 阿里镜像站(镜像站使用方法&#xff1a;查找最新非rc版本的golang安装包) golang安装包 - 中科大镜像站 go二进制文件下载 - 南京大学开源镜像站 Go语言官网(Google中国) Go语言官网(Go团队) 截至目前&#xff08;2023年9月17日&#x…

中秋猜灯谜小游戏

中秋猜灯谜小游戏是一个基于HTML制作的互动游戏&#xff0c;旨在增添中秋节的欢乐氛围&#xff0c;通过猜灯谜来娱乐和挑战玩家。 目录 前言简介游戏规则 制作过程HTML 结构CSS 样式JavaScript 交互 功能实现题目和答案的存储游戏逻辑设计 前言 简介 游戏开始时&#xff0c;玩…

SpringBoot Admin监控平台《二》基础报警设置

一、前置准备 首先搭建监控一个平台和连个客户端&#xff0c;搭建流程见SpringBoot Admin监控平台《一》平台搭建及基础介绍 &#xff0c;搭建完毕之后&#xff0c;启动各个项目&#xff0c;监控平台的界面如下所示&#xff1a; 二、邮件报警 2.1.邮箱授权码获取 授权码主要…

5.5V-65V Vin同步降压控制器,具有线路前馈SCT82630DHKR

描述&#xff1a; SCT82630是一款65V电压模式控制同步降压控制器&#xff0c;具有线路前馈。40ns受控高压侧MOSFET的最小导通时间支持高转换比&#xff0c;实现从48V输入到低压轨的直接降压转换&#xff0c;降低了系统复杂性和解决方案成本。如果需要&#xff0c;在低至6V的输…

天猫全店商品采集教程,天猫店铺所有商品接口(详解天猫店铺所有商品数据采集步骤方法和代码示例)

随着电商行业的快速发展&#xff0c;天猫已成为国内的电商平台之一&#xff0c;拥有着海量的商品资源。对于一些需要大量商品数据的商家或者需求方来说&#xff0c;天猫全店采集是非常必要的。本文将详细介绍天猫全店采集的步骤和技巧&#xff0c;帮助大家更好地完成数据采集任…

使用Visual Leak Detector排查内存泄漏问题

目录 1、VLD工具概述 2、下载并安装VLD 2.1、下载VLD 2.2、安装VLD 3、VLD安装目录及文件说明 3.1、安装目录及文件说明 3.2、关于32位和64位版本的详细说明 4、在工程中引入VLD 5、内存泄漏检测实例讲解 5.1、程序启动报错 5.2、启动调试&#xff0c;查看内存泄漏报…