CPU/GPU实现向量内积

向量内积(点乘/点积/数量积):两个向量对应元素相乘之后求和:

CPU实现: 

//cpu 实现一下向量内积#include<stdio.h>
template<typedef T>
void dot_mul(T *a, T *b, T *c, int n)
{   double tmp = 0;for(int i = 0; i < n; i++){tmp += a[i] * b[i];}*c = tmp;
}int main()
{//定义数组以及数组的大小float a[N], b[N];float c = 0;for(int i = 0; i < N; ++i){a[i] = i * 1.0;b[i] = 1.0}dot_cpu(a, b, &c, N);printf("a dot b output %f\n", c);printf("Hello World!\n");

首次接触bank conflict的概念,在这里补充一下。

bank是shared memory中用来存储数据的特殊组织方式。为了高效存取输入shared memory分为32个存储体(bank), 对应32个线程。每个bank有一个固定的带宽,可以同时服务一个线程的访问。当多个线程在一个时钟周期内访问一个bank的不同地址时,会产生bank conflict。因为bank的读取带宽不能高效的同时服务多个线程,因此需要需要解决bank conflict。有个不解的地方,是什么导致所有的thread都去访问同一个bank?

了解一个bank的属性:bank的宽度是指bank存储器的位宽。位宽是存储器连接的总线一次可以传数的数据量,可以是32bit,也可以是64bit,取决于总线的位数。可以是4字节/8字节。

避免bank conflict的方法有以下几种:

  • 使用不同的bank size,可以通过cudaDeviceSetSharedMemConfig函数来设置bank size为4字节或8字节,这样可以改变shared memory到bank的映射方式,减少冲突的可能性。
  • 使用memory padding,即在shared memory的数组中增加一些空白的元素,使得不同的线程访问不同的bank,从而避免冲突。
  • 使用不同的访问模式,比如使用转置或者重排的方式,使得一个warp中的线程访问不同的bank或者同一个地址,从而避免冲突。

回归正题,用cuda实现向量的内积(点积/点乘/数量积)。

单block分散归约法

 

第一次理解单block分散归约 takes 3 hours!

第一次手撸整理单block分散归约代码 takes one and a half hours!

main 函数 takes half an hour !

以下是我学习整理后的kernel函数:

#include "cuda_runtime.h"
#include "stdio.h"#define threadnums 32
#define N 2048//单block分散归约法
template <typedef T>
__global__ dotmul_gpu_1(T *a, T *b, T *c, int N)
{const int nThreadIdx = threadIdx.x;//当前线程ID索引const int nBlockDimX = blockDim.x;//一个block内开启的线程总数int nTid = nTreadIdx;dobule dTmp = 0.0;//开辟shared memory,大小与线程数量一致__shared__ T tmp[nBlockDimX];//step 1://每个线程负责 N/nBlockDimX 个元素相乘后的累加 while(nTid < N){dTmp += a[nTid] * b[nTid];nTid += nBlockDimX;}//每个线程将以上计算结果放入共享内存中tmp[nThreadIdx] = dTmp;//同步线程,等待所有线程完成以上计算__syncthreads();//step2:归约reductionint i = 2;int j = 1;while(i <= nBlockDimX){if(nThreadIdx / i == 0){//所有线程完成一次求和归约计算dTmp = tmp[nThreadIdx] + tmp[nThreadIdx + j];tmp[nThreadIdx] = dTmp;}__syncthreads();//这个地方利用i和j进行索引比较巧妙//32个线程进行求和归约,每次归约,线程索引的元素下标如下://第一次归约:0+1, 2+3, 4+5, 6+7, 8+9, 10+11, 12+13,14+15, 16+17, 18+19, 20+21, 22+23, 24+25, 26+27, 28+29, 30+31//第二次归约:0+2, 4+6, 8+10, 12+14, 16+18, 20+22, 24+26, 28+30 //第三次归约:0+4, 8+12, 16+20, 24+28//第四次归约:0+8, 16+24//第五次归约:0+16//求和归约值:0i *= 2;j *= 2;}//此处只在一个线程中获取向量内积值,因此需要线程ID判断if(0 == nTreadIdx)*c = tmp[0];
}

 主函数整理如下:

int main()
{float a[N], b[N];//对向量a[], b[]初始化值for(int i = 0; i < N; i++){a[i] = 1.0;b[i] = i * 1.0;}float *d_a=NULL, *d_b=NULL, *d_c=NULL;//将数组a[]的数据从CPU拷贝到GPUcudaMalloc(&d_a, N*sizeof(float));cudaMemcpyAsync(d_a, a, N*sizeof(float), cudaMemcpyHostToDevice);//将数组b[]的数据从CPU拷贝到GPUcudaMalloc(&d_b, N*sizeof(float));cudaMemcpyAsync(d_b, b, N*sizeof(float), cudaMemcpyHostToDevice);//不要忘记了结果也需要存储在显存上!cudaMalloc(&d_c, sizeof(float));//调用kernel函数dim3 blocks(1,0,0);dim3 threadPerBlock(threadnums, 0, 0);dotmul_gpu_1<<<blocks, threadPerBlock>>>(d_a, d_b, d_c, N);//分配的显存需要手动释放cudaFree(d_a);cudaFree(d_b);cudaFree(d_c);return 0;
}

 参考链接:

CUDA学习(十):向量内积的多种方法实现_为向量类增加计算内积的功能。-CSDN博客

拯救你的CUDA!什么是bank,为什么会发生bank conflict???_哔哩哔哩_bilibili

 该方法存在的问题在参考文章中被指出有违背访问对其原则、容易产生bank conflict。后面再一一学习补充。

此外,解决cuda上向量内积的方法还有,留待后续学习补充:

单Block低线程归约向量内积

多block向量内积

cublas库实现向量内积

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

三层交换机实现不同VLAN间通讯

默认时&#xff0c;同一个VLAN中的主机才能彼此通信&#xff0c;那么交换机上的VLAN用户之间如何通信&#xff1f; 要实现VLAN之间用户的通信&#xff0c;就必须借助路由器或三层交换机来完成。 下面以三层交换机为例子说明&#xff1a; 注意&#xff1a; 1.交换机与三层交换…

uni-app 使用vscode开发uni-app

安装插件 uni-create-view 用于快速创建页面 配置插件 创建页面 输入页面名称&#xff0c;空格&#xff0c;顶部导航的标题&#xff0c;回车 自动生成页面并在pages.json中注册了路由 pages\login\login.vue <template><div class"login">login</d…

python-opencv 培训课程笔记(1)

python-opencv 培训课程笔记&#xff08;1&#xff09; 博主参加了一次opencv库的培训课程&#xff0c;把课程所学整理成笔记&#xff0c;供大家学习&#xff0c;第一次课程包括如下内容&#xff1a; 1.读取图像 2.保存图像 3.使用opencv库显示图像 4.读取图像为灰度图像 …

现货白银MACD实战分析例子

MACD这个技术指标的全称是平滑异同移动平均线&#xff0c;主要表示经过平滑处理后均线的差异程度&#xff0c;一般用来研判现货白银价格变化的方向、强度和趋势。MT4中的MACD指标&#xff0c;主要是由信号线、&#xff08;上升/下跌&#xff09;动能柱、0轴这三部分组成。 MACD…

9、传统计算机视觉 —— 边缘检测

本节介绍一种利用传统计算机视觉方法来实现图片边缘检测的方法。 什么是边缘检测? 边缘检测是通过一些算法来识别图像中物体之间,或者物体与背景之间的边界,也就是边缘。 边缘通常是图像中灰度变化显著的地方,标志着不同区域的分界线。 在一张图像中,边缘可以是物体的…

新能源充电桩工业4G路由器应用,推动绿色出行,响应环保理念

在智慧城市环保事业发展领域&#xff0c;新能源技术应用成熟&#xff0c;物联网技术越来越广泛&#xff0c;充电桩物联网成为了智慧城市建设的热门应用。充电桩作为新能源汽车的重要配套设施&#xff0c;对于节能减排和推动环保理念可持续发展具有重要意义。而工业4G路由器作为…

css 实现文字流光效果

经过调研发现大多滑块验证码中&#xff0c;有一些文字流光效果&#xff0c;因此在这里简单实现一下。 实现主要利用background 渐变背景以及backgorund-clip:text实现。具体代码如下 css部分 .slide {width: 300px;height: 40px;border: 1px solid #ccc;border-radius: 8px;…

医院陪诊服务预约小程序的作用如何

对陪诊服务提供者及需求者来说&#xff0c;平台很重要&#xff0c;对服务提供者而言&#xff0c;通过微信私信/电话联系的形式很容易出现漏服务的情况&#xff0c;如遇需求者内容/地址/联系方式/哪家医院等信息提供不清或临时改变主意等&#xff0c;非常烦恼&#xff0c;同时各…

面试题c/c++--语言基础

一 、语言基础 1.1 指针 野指针&#xff1a;指针指向的位置是不可知的 悬空指针&#xff1a;指针最初指向的内存已经被释放了的一种指针 两种指针都指向无效内存空间&#xff0c; 即不安全不可控 。需要在定义指针后且在使用之前完成初始化或者使用 智能指针来避免 智能指针 智…

html主页框架,前端首页通用架构,layui主页架构框架,首页框架模板

html主页框架 前言功能说明效果使用初始化配置菜单加载主题修改回调 其他非iframe页面内容使用方式iframe页面内容使用方式 前言 这是一个基于layui、jquery实现的html主页架构 平时写的系统后台可以直接套用此框架 由本人整合编写实现&#xff0c;简单上手&#xff0c;完全免…

Python开源自动化工具Playwright安装及介绍

一个非常强大的自动化项目叫 playwright-python 它支持主流的浏览器&#xff0c;包含&#xff1a;Chrome、Firefox、Safari、Microsoft Edge 等&#xff0c;同时支持以无头模式、有头模式运行&#xff0c;并提供了同步、异步的 API&#xff0c;可以结合 Pytest 测试框架 使用&…

系列五、线程间通信

一、synchronized实现 1.1、案例一&#xff08;2个线程交替对变量执行1、-1操作&#xff0c;来10轮&#xff09; 1.1.1、资源类ShareDataOne /*** Author : 一叶浮萍归大海* Date: 2023/11/20 10:44* Description: 资源类* 说明&#xff1a;2个线程使用if判断变量的值&#…

企业微信获取第三方应用凭证

上一篇介绍了如何配置通用开发参数及通过url回调验证&#xff0c; 本篇将通过服务商后台配置关联小程序应用配置和获取第三方凭证及如何配置企业可信IP。 当然上篇配置的回调设置也不会白费&#xff0c;在下方的指令和数据回调会用到。 第三方应用开发流程 官方企业微信第三方…

微服务学习|Nacos配置管理:统一配置管理、配置热更新、配置共享、搭建Nacos集群

统一配置管理 在微服务当中&#xff0c;提供一个配置中心来将一些配置提取出来&#xff0c;进行统一的使用&#xff0c;Nacos既可以充当注册中心&#xff0c;也提供配置中心的功能。 1.在Nacos中添加配置文件 在Nacos控制台&#xff0c;我们可以在配置管理中&#xff0c;添加…

servlet乱码问题

问题&#xff1a;中文乱码 解决&#xff1a;加框的部分

「Verilog学习笔记」ROM的简单实现

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点&#xff0c;刷题网站用的是牛客网 分析 要实现ROM&#xff0c;首先要声明数据的存储空间&#xff0c;例如&#xff1a;[3:0] rom [7:0]&#xff1b;变量名称rom之前的[3:0]表示每个数据具有多少位&#xff0…

云原生微服务-理论篇

文章目录 分布式应用的需求分布式架构治理模式演进ESB 是什么&#xff1f;微服务架构 MSA微服务实践细节微服务治理框架sidercar 什么是service mesh&#xff1f;康威定律微服务的扩展性什么是MSA 架构&#xff1f;中台战略和微服务微服务总体架构组件微服务网关服务发现与路由…

成都优优聚美团代运营:塑造卓越优势,引领电商新时代

在当今这个数字化时代&#xff0c;美团作为中国最大的本地生活服务平台之一&#xff0c;正在为消费者和商家搭建一个无缝链接的桥梁。而在成都&#xff0c;有一家名为优优聚美团代运营的公司&#xff0c;他们凭借着专业的技能和高效的服务&#xff0c;成为了美团平台上的佼佼者…

Spring IOC - Bean的生命周期之依赖注入

在Spring启动流程中&#xff0c;创建的factoryBean是DefaultListableBeanFactory&#xff0c;其类图如下所示&#xff1a; 可以看到其直接父类是AbstractAutoireCapableBeanFactory&#xff0c;他主要负责完成Bean的自动装配和创建工作。 具体来说&#xff0c;AbstractAutowire…

MySQL 之多版本并发控制 MVCC

MySQL 之多版本并发控制 MVCC 1、MVCC 中的两种读取方式1.1、快照读1.2、当前读 2、MVCC实现原理之 ReadView2.1、隐藏字段2.2、ReadView2.3、读已提交和可重复读隔离级别下&#xff0c;产生 ReadView 时机的区别 3、MVCC 解决幻读4、总结 MVCC&#xff08;多版本并发控制&…