CUDA学习笔记7——CUDA内存组织
CUDA内存组织
CUDA设备内存的分类与特征
内存类型 | 物理位置 | 访问权限 | 可见范围 | 生命周期 | |
---|---|---|---|---|---|
1 | 全局内存 | 芯片外 | 可读写 | 所有线程和主机端 | 由主机分配与释放 |
2 | 常量内存 | 芯片外 | 只读 | 所有线程和主机端 | 由主机分配与释放 |
3 | 纹理和表面内存 | 芯片外 | 一般只读 | 所有线程和主机端 | 由主机分配与释放 |
4 | 寄存器内存 | 芯片内 | 可读写 | 单个线程 | 所在线程 |
5 | 局部内存 | 芯片外 | 可读性 | 单个线程 | 所在线程 |
6 | 共享内存 | 芯片内 | 可读性 | 单个线程块 | 所在线程块 |
-
全局内存:核函数中所有线程都能访问其中的数据。
用cudaMalloc()为全局内存变量分配设备内存;
用cudaMemcpy()将主机数据复制到全局内存; -
常量内存:一共64KB,只读,可见范围与生命周期与全局内存一样,访问速度比全局内存快;在核函数未满用 _constant_ 定义变量;并使用cudaMemcpyToSymbol()将数据从主机端复制到设备的常量内存。
-
纹理内存与表面内存:类似于常量内存(可见范围与生命周期相同);
-
寄存器:在核函数中定义的不加任何限定符的变量一般来说放在寄存器中,核函数定义不加任何限定符的数组可能放于寄存器,也可能放于局部内存中;
-
局部内存:寄存器放不下的变量,索引值不能在编译时确定的数组;
-
共享内存:与寄存器类似,存在于芯片上,仅次于寄存器的读写速度;
CUDA中的内存组织示意图
GPU设备规格查询
#include <stdio.h>
#include "cuda_runtime.h"
#include "device_launch_parameters.h"int main()
{int device_id = 0;cudaDeviceProp prop;cudaGetDeviceProperties(&prop, device_id);printf("Device id: %d\n", device_id);printf("Device name: %s\n", prop.name);printf("Compute capability: %d.%d\n", prop.major, prop.minor);printf("Amount of global memory: %g GB\n", prop.totalGlobalMem / 1024.0);printf("Amount of constant memory: %g KB\n", prop.totalConstMem / 1024.0);printf("Maximum grid size: %d %d %d\n",prop.maxGridSize[0], prop.maxGridSize[1], prop.maxGridSize[2]);printf("Maximum block size: %d %d %d\n", prop.maxThreadsDim[0], prop.maxThreadsDim[1], prop.maxThreadsDim[2]);printf("Number of SMs: %d\n", prop.multiProcessorCount);printf("----------------------------- \n");printf("Maximum amount of shared memory per block: %g KB\n", prop.sharedMemPerBlock / 1024.0);printf("Maximum amount of shared memory per SM: %g KB\n",prop.sharedMemPerMultiprocessor / 1024.0);printf("Maximum number of registers per block: %d K\n", prop.regsPerBlock / 1024.0);printf("Maximum number of registers per SM: %d K\n", prop.regsPerMultiprocessor / 1024.0);printf("Maximum number of threads per block: %d \n", prop.maxThreadsPerBlock);printf("Maximum number of threads per SM: %d \n", prop.maxThreadsPerMultiProcessor);return 0;
}
全局内存的合并与非合并访问
合并访问:一个线程束对全局内存的一次访问(读/写)导致最少数量的数据传输;否则为非合并访问。
利用共享内存和统一内存优化矩阵乘
#include <stdio.h>
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include<math.h>
#include <malloc.h>
#include <opencv2/opencv.hpp>
#include <stdlib.h>//利用share memory 和统一内存优化矩阵乘#define M 1000
#define N 500
#define K 1000__managed__ int a[M*N];
__managed__ int b[N*K];
__managed__ int c_gpu[M*K];
__managed__ int c_cpu[M*N];#define BLOCK_SIZE 16__global__ void gpu_matrix(int* a, int* b, int* c, int m, int n, int k)
{__shared__ int sub_a[BLOCK_SIZE][BLOCK_SIZE];__shared__ int sub_b[BLOCK_SIZE][BLOCK_SIZE];int x = blockIdx.x*blockDim.x + threadIdx.x;int y = blockIdx.y*blockDim.y + threadIdx.y;int tmp = 0;int idx;for (int step = 0; step < N/BLOCK_SIZE; step++){int step_x = step*BLOCK_SIZE + threadIdx.x;int step_y = y;idx = step_y*n + step_x;if (step_x>n || step_y>m){sub_a[threadIdx.y][threadIdx.x] = 0;}else{sub_a[threadIdx.x][threadIdx.x] = a[idx];}step_x = x;step_y = step*BLOCK_SIZE + threadIdx.y;idx = step * k + step_x;if (step_x >= k || step_y>=n){sub_b[threadIdx.y][threadIdx.x] = 0;}else{sub_b[threadIdx.y][threadIdx.x] = b[idx];}__syncthreads();for (int i = 0; i < BLOCK_SIZE; i++){tmp += sub_a[threadIdx.y][i] * sub_b[i][threadIdx.x];}__syncthreads();}if (x<k && y<m){c[y*k + x] = tmp;}}void cpu_matrix(int* a, int* b, int* c, int m, int n, int k)
{for (int y = 0; y < m; y++){for (int x = 0; x < k; x++){int tmp = 0;for (int step = 0; step < n; step++){tmp += a[y*n + step] * b[step*n + x];}c[y*k + x] = tmp;}}}int main()
{for (int y = 0; y < M; y++){for (int x = 0; x < N; x++){a[y * N + x] = rand() % 1024;}}for (int y = 0; y < N; y++){for (int x = 0; x < K; x++){b[y*K + x] = rand() % 1024;}}unsigned int grid_x = (K + BLOCK_SIZE - 1) / BLOCK_SIZE;unsigned int grid_y = (M + BLOCK_SIZE - 1) / BLOCK_SIZE;dim3 dimGrid(grid_x, grid_y);dim3 dimBlock(BLOCK_SIZE, BLOCK_SIZE);gpu_matrix<<<dimGrid, dimBlock>>>(a, b, c_gpu, M, N, K);cpu_matrix(a, b, c_cpu, M, N, K);bool errors = false;for (int y = 0; y < M; y++){for (int x = 0; x < K; x++){if (fabs(c_cpu[y*K + x] - c_gpu[y*K + x]) > (1.0e-10)){errors = true;}}}printf("Result: %s\n", errors ? "Error" : "Pass");return 0;
}
相关文章:

CUDA学习笔记7——CUDA内存组织
CUDA内存组织 CUDA设备内存的分类与特征 内存类型物理位置访问权限可见范围生命周期1全局内存芯片外可读写所有线程和主机端由主机分配与释放2常量内存芯片外只读所有线程和主机端由主机分配与释放3纹理和表面内存芯片外一般只读所有线程和主机端由主机分配与释放4寄存器内存…...
C#把自启动程序添加到注册表中
1.Regedit自启动注册表路径 计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run 2.获取运行程序路径 SetAutoStart(AppDomain.CurrentDomain.FriendlyName, AppDomain.CurrentDomain.BaseDirectory); 3.添加到注册表中,如果注册表已经存…...

Java面试题(每天10题)-------连载(26)
目录 多线程篇 1、什么是FutureTask? 2、什么是同步容器和并发容器的实现? 3、什么是多线程的上下文切换? 4、ThreadLocal的设计理念与作用? 5、ThreadPool(线程池)用法与优势? 6、Concur…...

通用型 SPI-Flash 相关知识汇总(w25q16\q64,gd25q128\q256)
目录 管脚定义: 常用指令: GD25q16: gd25Q28 编辑 gw25q16 编辑 芯片丝印说明: GD系列: winbond系列: Read Identification(9FH): 常见ID: GD: 编辑…...

鸿蒙原生应用开发-DevEco Studio超级终端模拟器的使用
一、了解超级终端模拟器支持的设备情况 该特性在DevEco Studio V2.1 Release及更高版本中支持。 目前超级终端模拟器支持“PhonePhone”、“PhoneTablet”和“PhoneTV”的设备组网方式,开发者可以使用该超级终端模拟器来调测具备跨设备特性的应用/服务,如…...

抖音AAN服务商有几家?
大家都知道抖音服务商多如牛毛,有本地生活服务商,MCN机构服务商,企业认证服务商,ISV服务商等等。但是aan服务商就屈指可数。 aan技术服务商 从关系层面讲,aan服务商的关系友好到啥程度呢,就好比微信指定了…...

10-26 maven配置
打开idea 打开setting 基于Idea创建idea项目 加载jar包:(一般需要自己去手动加入,本地仓库是没有的)...
贰[2],OpenCV函数解析
1,imread:图片读取 CV_EXPORTS_W Mat imread( const String& filename, int flags IMREAD_COLOR );//参数1(filename):文件地址 //参数2(flags):读取标志 注:ImreadModes,参数2(flags)枚举定义 enum ImreadModes { IMREAD…...

探秘Python闭包与作用域
文章目录 闭包的定义与作用LEGB规则nonlocal与global关键字在Python的世界里,理解闭包(Closure)和作用域(Scope)是提升编程技巧和深度的一大步。这篇文章将带你深入了解闭包的神秘面纱,掌握LEGB规则,并使用nonlocal与global关键字来巧妙控制变量作用域。 闭包的定义与作…...

GPT-4V:AI在教育领域的应用
OpenAI于9月25日发布了最新的GPT-4V模型,为ChatGPT引入了语音和图像功能,为用户提供更多元化的使用方式。这次更新将为用户带来更便捷、直观的交互体验,用户可以直接拍照上传并针对照片内容提出问题。OpenAI的最终目标是构建安全、有益的人工…...
自动化之Java面试
1.重写与重载的区别 重载规则: 方法名相同,参数个数或类型不同,与返回值类型无关,节约词汇,例如driver.switchTo().frame(index/nameOrId/frameElement) java的重载(overload) 最重要的应用场景就是构造器…...

Redis中的Zset类型
目录 Zset的相关命令 zadd zrange zcard zcount zrevrange zrangebyscore zpopmax bzpopmax zpopmin和bzpopmin zrank zrevrank zscore zrem zremrangebyrank zremrangebyscore 操作集合间的命令 zinterstore和zunionstore 内部编码 Zset的应用场景 Zset表…...
Python行对齐工具difflib
1 用途 1.1 功能 对比两个字符串数组之间的差异,以第一个参数为基准,与第二个参数比较。 1.2 使用场景 一个原文件,一个改过的文件,对比差异;一个纯文本,一个带格式的,对比差异;…...

Flutter利用GridView创建网格布局实现优美布局
文章目录 简介使用详解导入依赖项创建一个基本的 GridView一些参数说明使用GridView.count来构造 其他控制总结 简介 GridView 是 Flutter 中用于创建网格布局的强大小部件。它允许你在行和列中排列子小部件,非常适合显示大量项目,例如图像、文本、卡片…...
IDEA 基本配置
IDEA 基本配置 1、基本样式2、环境参数3、基本插件4、参考 1、基本样式 设置全局字体大小 配置font 字体大小:15 配置类注释 /** ** Author: ${USER}* Date: ${YEAR}-${MONTH}-${DAY} ${HOUR}:${MINUTE}* Version: 1.0.0 */配置注释keymap 添加 注释 ccm&…...
计算机组成原理平时作业一
计算机组成原理平时作业一 1.单选题 1.1计算机中使用总线结构便于增减外设,同时(c )。 a.减少了信息传输量 b.提高了信息传输量 c.减少了信息传输量的条数 d.三者均正确 答案解析: 概念规定 1.2在定点补码运算器中,…...

iOS Crash 治理:淘宝VisionKitCore 问题修复
本文通过逆向系统,阅读汇编指令,逐步找到源码,定位到了 iOS 16.0.<iOS 16.2 WKWebView 的系统bug 。同时苹果已经在新版本修复了 Bug,对于巨大的存量用户,仍旧会造成日均 Crash pv 1200 uv 1000, 最终通…...
NSSM部署window服务
nssm 下载 安装服务:nssm install <servicename> 启动服务:nssm start <servicename> 停止服务:nssm stop <servicename> 重启服务: nssm restart <servicename> 删除创建的servername服务: nssm remove <service…...
Go语言数据类型
文章目录 Go语言数据类型一、布尔类型二、数字类型三、字符串类型四、派生类型 Go语言数据类型 在 Go 编程语言中,数据类型用于声明函数和变量。 数据类型的出现是为了把数据分成所需内存大小不同的数据,编程的时候需要用大数据的时候才需要申请大内存…...

Python爬取汽车之家二手车数据并作可视化
大家早好、午好、晚好吖 ❤ ~欢迎光临本文章 如果有什么疑惑/资料需要的可以点击文章末尾名片领取源码 课程亮点: 1、系统分析目标网页 2、html标签数据解析方法 3、海量数据一键保存 获取二手车数据 环境介绍: python 3.8 pycharm 2022.3专业版 requests >>>…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...

Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...

Android15默认授权浮窗权限
我们经常有那种需求,客户需要定制的apk集成在ROM中,并且默认授予其【显示在其他应用的上层】权限,也就是我们常说的浮窗权限,那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...

企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...

听写流程自动化实践,轻量级教育辅助
随着智能教育工具的发展,越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式,也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建,…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...
Redis:现代应用开发的高效内存数据存储利器
一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发,其初衷是为了满足他自己的一个项目需求,即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源,Redis凭借其简单易用、…...