当前位置: 首页 > news >正文

【模型推理优化学习笔记】CUDA加速矩阵乘计算

矩阵乘可以利用gpu多线程并行的特点进行加速计算,但是传统简单的方法需要多次读取数据到寄存器中,增加耗时,因此利用gpu的共享内存可以被一个block内的所有线程访问到的特性,结合tiling技术进行加速计算。
理论部分不解释了,网上有很多,关键在于网上很多利用共享内存计算的代码存在错误(大部分只有在设置blockDim.x == blockDim.y 的时候,凑巧能对齐index给出正确的结果,若这俩不等,结果就错了),这里给出一个修正的版本:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <assert.h>
#include "cuda_runtime.h"
#include "device_launch_parameters.h"#define M 32
#define K 32
#define N 32void initial(float *array, int size)
{for (int i = 0; i < size; i++){array[i] = (float)(1);}
}void printMatrix(float *array, int row, int col)
{float *p = array;for (int y = 0; y < row; y++){for (int x = 0; x < col; x++){printf("%.2f ", p[x]);}p = p + col;printf("\n");}return;
}__global__ void multiplicateMatrixOnDevice(float *array_A, float *array_B, float *array_C, int M_p, int K_p, int N_p)
{int ix = threadIdx.x + blockDim.x*blockIdx.x;//row numberint iy = threadIdx.y + blockDim.y*blockIdx.y;//col numberif (ix < N_p && iy < M_p){float sum = 0;for (int k = 0; k < K_p; k++){sum += array_A[iy*K_p + k] * array_B[k*N_p + ix];}array_C[iy*N_p + ix] = sum;}
}// Compute C = A * B
//  M, K, K, N, M, N
__global__ void matrixMultiplyShared(float *A, float *B, float *C,int numARows, int numAColumns, int numBRows, int numBColumns, int numCRows, int numCColumns)
{//@@ Insert code to implement matrix multiplication here//@@ You have to use shared memory for this MP// 1. 相比网上代码,修改这里的index__shared__ float sharedM[8][16];  __shared__ float sharedN[16][8];  int bx = blockIdx.x;  int by = blockIdx.y; int tx = threadIdx.x; int ty = threadIdx.y; int row = by * blockDim.y + ty;     int col = bx * blockDim.x + tx;     float Csub = 0.0;// for (int i = 0; i < 2; ++i)     for (int i = 0; i < (int)(ceil((float)numAColumns / blockDim.x)); i++){if (i*blockDim.x + tx < numAColumns && row < numARows)sharedM[ty][tx] = A[row*numAColumns + i*blockDim.x + tx];elsesharedM[ty][tx] = 0.0;// 2. 相比网上代码,修改这里的indexif (i*blockDim.x + tx < numBRows && col < numBColumns)sharedN[tx][ty] = B[(i*blockDim.x + tx)*numBColumns + col];elsesharedN[tx][ty] = 0.0;__syncthreads();// if (blockIdx.x == 0 && blockIdx.y == 1 && threadIdx.x == 0 && threadIdx.y ==0 ) {//     printf("sharedM: \n");//     for (int i = 0; i < 8; ++i) {//         for (int j = 0; j < 16; ++j) {//             printf("%f ", sharedM[i][j]);//         }//         printf("\n");//     }//     printf("sharedN: \n");//     for (int i = 0; i < 16; ++i) {//         for (int j = 0; j < 8; ++j) {//             printf("%f ", sharedM[i][j]);//         }//         printf("\n");//     }// }for (int j = 0; j < blockDim.x; j++)// 3. 相比网上代码,修改这里的indexCsub += sharedM[ty][j] * sharedN[j][ty];__syncthreads();}if (row < numCRows && col < numCColumns)C[row*numCColumns + col] = Csub;}int main(int argc, char **argv)
{clock_t start = 0, finish = 0;float time;int Axy = M * K;int Bxy = K * N;int Cxy = M * N;float *h_A, *h_B, *hostRef, *deviceRef;h_A = (float*)malloc(Axy * sizeof(float));h_B = (float*)malloc(Bxy * sizeof(float));int nBytes = M * N * sizeof(float);hostRef = (float*)malloc(Cxy * sizeof(float));deviceRef = (float*)malloc(Cxy * sizeof(float));initial(h_A, Axy);initial(h_B, Bxy);// printMatrix(h_A, M, K);float *d_A, *d_B, *d_C;cudaMalloc((void**)&d_A, Axy * sizeof(float));cudaMalloc((void**)&d_B, Bxy * sizeof(float));cudaMalloc((void**)&d_C, Cxy * sizeof(float));cudaMemcpy(d_A, h_A, Axy * sizeof(float), cudaMemcpyHostToDevice);cudaMemcpy(d_B, h_B, Bxy * sizeof(float), cudaMemcpyHostToDevice);int dimx = 16;int dimy = 16;dim3 block(dimx, dimy);dim3 grid((M + block.x - 1) / block.x, (N + block.y - 1) / block.y);cudaEvent_t gpustart, gpustop;float elapsedTime = 0.0;cudaEventCreate(&gpustart);cudaEventCreate(&gpustop);cudaEventRecord(gpustart, 0);// multiplicateMatrixOnDevice<<<grid,block>>> (d_A, d_B, d_C, M, K, N);matrixMultiplyShared << < grid, block >> > (d_A, d_B, d_C, M, K, K, N, M, N);cudaDeviceSynchronize();cudaEventRecord(gpustop, 0);cudaEventSynchronize(gpustop);cudaEventElapsedTime(&elapsedTime, gpustart, gpustop);cudaEventDestroy(gpustart);cudaEventDestroy(gpustop);cudaMemcpy(deviceRef, d_C, Cxy * sizeof(float), cudaMemcpyDeviceToHost);printMatrix(deviceRef, M, N);return 0;
}

相关文章:

【模型推理优化学习笔记】CUDA加速矩阵乘计算

矩阵乘可以利用gpu多线程并行的特点进行加速计算&#xff0c;但是传统简单的方法需要多次读取数据到寄存器中&#xff0c;增加耗时&#xff0c;因此利用gpu的共享内存可以被一个block内的所有线程访问到的特性&#xff0c;结合tiling技术进行加速计算。 理论部分不解释了&#…...

第三届 “鹏城杯”(初赛)

第三届 “鹏城杯”&#xff08;初赛&#xff09; WEB Web-web1 反序列化tostring打Hack类 Payload:O%3A1%3A%22H%22%3A1%3A%7Bs%3A8%3A%22username%22%3BO%3A6%3A%22Hacker%22%3A2%3A%7Bs%3A11%3A%22%00Hacker%00exp%22%3BN%3Bs%3A11%3A%22%00Hacker%00cmd%22%3BN%3B%7D%7D…...

React Hooks为什么要在顶层使用?

为什么必须在函数顶层使用hooks&#xff1f; 使用过 hooks 的小伙伴应该都会发现&#xff0c;hooks只能在函数式组件的顶层使用&#xff0c;不能在循环&#xff0c;条件或嵌套函数中调用 Hook。 为什么呢&#xff1f; 查阅了很多答案&#xff0c;总结如下&#xff1a; hook…...

Vscode Vim自动切换

在VsCode里安装了Vim插件&#xff0c;由于Vim插件存在Normal和Insert两种模式&#xff0c;会需要经常性的按shift切换中英文&#xff0c;太过麻烦&#xff0c;本文介绍一下如何通过im-select来解决。 首先先确保自己的电脑里装有英文语言包&#xff0c;win10系统下可以使用Win…...

C语言初学1:详解#include <stdio.h>

一、概念 #include <stdio.h> 称为编译预处理命令&#xff0c;它在告诉C编译器在编译时包含stdio.h文件&#xff0c;如果在代码中&#xff0c;调用了这个头文件中的函数或者宏定义&#xff0c;则需引用该头文件。 二、作用 stdio.h是c语言中的标准输入输出的头文件&am…...

5 Tensorflow图像识别(下)模型构建

上一篇&#xff1a;4 Tensorflow图像识别模型——数据预处理-CSDN博客 1、数据集标签 上一篇介绍了图像识别的数据预处理&#xff0c;下面是完整的代码&#xff1a; import os import tensorflow as tf# 获取训练集和验证集目录 train_dir os.path.join(cats_and_dogs_filter…...

OpenCV 图像复制和图像区域读写

图像复制 共享数据, 使用 new Mat(srcMat, ...) 和 newMatsrcMat 生成新的Mat都和原Mat共享数据, 也就是说如果修改某一Mat,其他Mat也会随之改变复制全新的Mat, 使用CopyTo() 和 Clone() 方法将生成一个全新的Mat, 新Mat和原Mat不共享数据. 图像区域和点的读写 区域读取: 通过s…...

【分布式事务】初步探索分布式事务的概率和理论,初识分布式事的解决方案 Seata,TC 服务的部署以及微服务集成 Seata

文章目录 一、分布式服务案例1.1 分布式服务 demo1.2 演示分布式事务问题 二、分布式事务的概念和理论2.1 什么是分布式事务2.2 CAP 定理2.3 BASE 理论2.4 分布式事务模型 三、分布式事务解决方案 —— Seata3.1 什么是 Seata3.2 Seata 的架构3.3 Seata 的四种分布式事务解决方…...

es6过滤对象里面指定的不要的值filter过滤

//过滤出需要的值this.dataItemTypeSelectOption response.data.filter(ele > ele.dictValue tree||ele.dictValue float4);//过滤不需要的值this.dataItemTypeSelectOption response.data.filter((item) > {return item.dictValue ! "float4"&&it…...

Docker从入门到上天系列第二篇:传统虚拟机和容器的对比以及Docker的作用以及所解决的问题

大神推荐:作者有幸结识技术大神孙哥为好友获益匪浅,现在把孙哥作为朋友分享给大家。 孙哥链接:孙哥个人主页 作者简介:一个颜值99分,只比孙哥差一点的程序员。 本专栏简介:话不多说,让我们一起干翻Docker 本文章简介:话不多说,让我们讲清楚首先讲清楚Docker是什么 文章…...

共话医疗数据安全,美创科技@2023南湖HIT论坛,11月11日见

11月11日浙江嘉兴 2023南湖HIT论坛 如约而来 深入数据驱动运营管理、运营数据中心建设、数据治理和数据安全、数据资产“入表”等热点、前沿话题 医疗数据安全、数字化转型深耕者—— 美创科技再次深入参与 全新发布&#xff1a;医疗数据安全白皮书 深度探讨&#xff1a;数字…...

乐园要吸引儿童还是家长?万达宝贝王2000万会员的求精之路

2023年6月&#xff0c;万达宝贝王正式迈入“400店时代”。 万达宝贝王在全国200多座城市&#xff0c;以游乐设施、主题活动、成长课程服务10亿多用户&#xff0c;拥有2000多万名会员&#xff0c;是真正的国内儿童乐园领跑者。 当流量时代变成“留量”时代&#xff0c;用户增长…...

ps人像怎么做渐隐的效果?

photoshop怎么制作人像渐隐的图片效果&#xff1f;渐隐效果需要使用渐变来实现&#xff0c;下面我们就来看看详细的教程。 首先&#xff0c;我们打开Photoshop&#xff0c;点击屏幕框选的【打开】&#xff0c;打开一张背景图片。 下面&#xff0c;我们点击左上角【文件】——【…...

为什么IN操作符一般比OR操作符清单执行更快

IN操作符一般比OR操作符清单执行更快的主要原因有以下几点&#xff1a; 查询优化&#xff1a;数据库管理系统通常会针对IN操作符进行更好的查询优化。它可以使用哈希表或二叉搜索树等数据结构来更快地查找匹配的值&#xff0c;从而减少了搜索时间。而OR操作符需要逐个比较每个条…...

GPT-4-Turbo的128K长度上下文性能如何?超过73K Tokens的数据支持依然不太好!

本文原文来自DataLearnerAI官方网站&#xff1a;GPT-4-Turbo的128K长度上下文性能如何&#xff1f;超过73K Tokens的数据支持依然不太好&#xff01; | 数据学习者官方网站(Datalearner)https://www.datalearner.com/blog/1051699526438975 GPT-4 Turbo是OpenAI最新发布的号称…...

osg之黑夜背景地月系显示

目录 效果 代码 效果 代码 /** * Lights test. This application is for testing the LightSource support in osgEarth. * 灯光测试。此应用程序用于测试osgEarth中的光源支持。 */ #include "stdafx.h" #include <osgViewer/Viewer> #include <osgEarth/N…...

持续交付-Jenkinsfile 语法

实现 Pipeline 功能的脚本语言叫做 Jenkinsfile&#xff0c;由 Groovy 语言实现。Jenkinsfile 一般是放在项目根目录&#xff0c;随项目一起受源代码管理软件控制&#xff0c;无需像创建"自由风格"项目一样&#xff0c;每次可能需要拷贝很多设置到新项目&#xff0c;…...

IDEA重新choose source

大概现状是这样&#xff1a;之前有个工程&#xff0c;依赖了别的模块基础包&#xff0c;但当时并没有依赖包的源码工程&#xff0c;因此&#xff0c;通过鼠标左键点进去&#xff0c;看到的是jar包里的class文件&#xff0c;注释什么的都去掉了的&#xff0c;不好看。后面有这个…...

解析虚拟文件系统的调用

Linux 可以支持多达数十种不同的文件系统。它们的实现各不相同&#xff0c;因此 Linux 内核向用户空间提供了虚拟文件系统这个统一的接口&#xff0c;来对文件系统进行操作。它提供了常见的文件系统对象模型&#xff0c;例如 inode、directory entry、mount 等&#xff0c;以及…...

佳能相机拍出来的dat文件怎么修复为正常视频

3-3 佳能相机是普通人用得最多的相机之一&#xff0c;也有一些专业机会用于比较重要的场景&#xff0c;比如婚庆、会议录像、家庭录像使用等。 但作为电子产品&#xff0c;经常会出现一些奇怪的故障&#xff0c;最严重的应该就是拍出来的东西打不开了。 本文案例是佳能相机拍…...

React第五十七节 Router中RouterProvider使用详解及注意事项

前言 在 React Router v6.4 中&#xff0c;RouterProvider 是一个核心组件&#xff0c;用于提供基于数据路由&#xff08;data routers&#xff09;的新型路由方案。 它替代了传统的 <BrowserRouter>&#xff0c;支持更强大的数据加载和操作功能&#xff08;如 loader 和…...

ssc377d修改flash分区大小

1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)

概述 在 Swift 开发语言中&#xff0c;各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过&#xff0c;在涉及到多个子类派生于基类进行多态模拟的场景下&#xff0c;…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

Redis数据倾斜问题解决

Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中&#xff0c;部分节点存储的数据量或访问量远高于其他节点&#xff0c;导致这些节点负载过高&#xff0c;影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...

python报错No module named ‘tensorflow.keras‘

是由于不同版本的tensorflow下的keras所在的路径不同&#xff0c;结合所安装的tensorflow的目录结构修改from语句即可。 原语句&#xff1a; from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后&#xff1a; from tensorflow.python.keras.lay…...

三分算法与DeepSeek辅助证明是单峰函数

前置 单峰函数有唯一的最大值&#xff0c;最大值左侧的数值严格单调递增&#xff0c;最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值&#xff0c;最小值左侧的数值严格单调递减&#xff0c;最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...

代码规范和架构【立芯理论一】(2025.06.08)

1、代码规范的目标 代码简洁精炼、美观&#xff0c;可持续性好高效率高复用&#xff0c;可移植性好高内聚&#xff0c;低耦合没有冗余规范性&#xff0c;代码有规可循&#xff0c;可以看出自己当时的思考过程特殊排版&#xff0c;特殊语法&#xff0c;特殊指令&#xff0c;必须…...

MySQL 部分重点知识篇

一、数据库对象 1. 主键 定义 &#xff1a;主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 &#xff1a;确保数据的完整性&#xff0c;便于数据的查询和管理。 示例 &#xff1a;在学生信息表中&#xff0c;学号可以作为主键&#xff…...

抽象类和接口(全)

一、抽象类 1.概念&#xff1a;如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象&#xff0c;这样的类就是抽象类。 像是没有实际⼯作的⽅法,我们可以把它设计成⼀个抽象⽅法&#xff0c;包含抽象⽅法的类我们称为抽象类。 2.语法 在Java中&#xff0c;⼀个类如果被 abs…...