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

CUDA学习第二天: GPU核心与SM核心组件

1. CUDA的内存模型

每个线程有自己的私有本地内存(local memory) , 每个线快有包含共享内存, 可以被线程块中所有线程共享,其声明周期与线程块一致。

此外,所有的线程都可以访问全局内存(global memory) 还可以访问一些只读内存块: 常量内存(Constant Memory)和纹理内存(Texture Memory).

2. GPU的核心组件 – SM(Streaming Multiprocessor)

与CPU的多线程类似,一个Kernel实际上会启动很多线程,而多线程如果没有多核支持,在物理层也是无法实现并行的。

而GPU存在很多CUDA核心, 充分利用CUDA核心可以发挥GPU的并行计算能力。‘

SM的核心组件包括CUDA核心,共享内存,寄存器等,SM可以并发地执行数百个 线程,并发能力就取决与SM所拥有的资源数。

3.SIMI–(Single-Intruction, Multiple-Thread)单指令多线程

基本的执行单元是线程束(wraps),线程束包含32个线程,这些线程同时执行相同的指令,但是每个线程都包含自己的指令地址计数器和寄存器状态,也有自己独立的执行路径。

所以尽管线程束中的线程同时从同一程序地址执行,但是可能具有不同的行为,比如遇到了分支结构,一些线程可能进入这个分支,但是另外一些有可能不执行,它们只能死等,因为GPU规定线程束中所有线程在同一周期执行相同的指令,线程束分化会导致性能下降。

总之,就是网格和线程块只是逻辑划分一个kernel的所有线程其实在物理层是不一定同时并发的。所以kernel的grid和block的配置不同,性能会出现差异。另外,由于SM的基本执行单元是包含32个线程的线程束,所以block大小一般要设置为32的倍数。

4. 第一个CUDA示例,Cmake的配置等

#include <iostream>
#include <cuda.h>
#include <cuda_runtime.h>
#include <cuda_runtime_api.h>

void printDeviceProp(cudaDeviceProp& devProp, int dev)
{
	std::cout << "使用GPU device " << dev << ": " << devProp.name << std::endl;
    std::cout << "SM的数量:" << devProp.multiProcessorCount << std::endl;
    std::cout << "每个线程块的共享内存大小:" << devProp.sharedMemPerBlock / 1024.0 << " KB" << std::endl;
    std::cout << "每个线程块的最大线程数:" << devProp.maxThreadsPerBlock << std::endl;
    std::cout << "每个EM的最大线程数:" << devProp.maxThreadsPerMultiProcessor << std::endl;
    std::cout << "每个EM的最大线程束数:" << devProp.maxThreadsPerMultiProcessor / 32 << std::endl;
	
}


bool initCUDA(cudaDeviceProp& devProp)
{
	int count;
	cudaGetDeviceCount(&count);
	if(count == 0) {return false;};
	
	
	int i;
	for(i=0; i<count; i++)
	{
		if(cudaGetDeviceProperties(&devProp, i) == cudaSuccess)
		{
			if(devProp.major >= 1)
			{
				printDeviceProp(devProp, i);
				break;
			}
		}
	}
	
	if(i == count) {std::cout<<"CUDA can't support the device !"<<std::endl;	return false;};
	
	cudaSetDevice(i);
	
	return false;
}
int main()
{
    cudaDeviceProp devProp;
	
	if(initCUDA(devProp))
	{
		std::cout<<"CUDA initialized Succed. \n"<<std::endl;
	}
    //CHECK(cudaGetDeviceProperties(&devProp, dev));
    return 0;

}
  • CMakeLists.txt 的配置
cmake_minimum_required(VERSION 3.1)
project(CUDA_Toturials)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++11")

#set the default path for built executables to the "bin" directory
set(CMAKE_BUILD_TYPE Debug)

set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
SET( LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
LINK_DIRECTORIES( ${PROJECT_SOURCE_DIR}/lib)
INCLUDE_DIRECTORIES( ${PROJECT_SOURCE_DIR}/include )

# openMp for parallel
# find_package(OpenMP)
# if(OPENMP_FOUND)
# 	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
# 	set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
# endif()

find_package(CUDA 8.0 REQUIRED)
include_directories(${CUDA_INCLUDE_DIRS})

# 设置CUAD编译配置
set(CUDA_NVCC_FLAGS "-g -G")

# build option
set(GENCODE -gencode=arch=compute_35,code=sm_35)
set(GENCODE ${GENCODE} -gencode=arch=compute_30,code=sm_30)
set(GENCODE ${GENCODE} -gencode=arch=compute_20,code=sm_20)
set(GENCODE ${GENCODE} -gencode=arch=compute_10,code=sm_10)
set(GENCODE ${GENCODE} -gencode arch=compute_61,code=sm_61)

# 生成可执行文件
cuda_add_executable(main src/main.cpp)

# add_subdirectory(src)

相关文章:

  • DAVIS第四课:基于DAVIS的特征点检测和追踪
  • CUDA学习第三天:Kernel+grid+block关系
  • DAVIS第五课: 基于事件相机的一种几何实时3DSLAM算法
  • ubuntu学习技巧1:容易混淆但又重要的命令
  • RGB颜色空间对应的不同颜色列表
  • V-SLAM重读(1): SVO: Fast Semi-Direct Monocular Visual Odometry
  • C++11回顾学习(4): 语法解析之虚函数与继承
  • ROS回顾学习(10): 项目研究中遇到问题记录2
  • ROS深入学习(1): ROS程序简单调试方式
  • C++ 11回顾学习(5): STL中的vector - map - pair对比
  • V-SLAM重读(2): DSO: Direct Sparse Odometry (DSO)
  • VLP-16第一课: Velodyne的工作原理和驱动安装
  • ubuntu技巧学习3: 将视频转换为gif动态图
  • V-SLAM重读(3):SVO代码阅读和调试修改
  • VLP-16第二课: 学习论文LeGo-LOAM: 基于地面优化的轻量级雷达里程计和地图构建
  • [微信小程序] 使用ES6特性Class后出现编译异常
  • 《Javascript数据结构和算法》笔记-「字典和散列表」
  • 【跃迁之路】【444天】程序员高效学习方法论探索系列(实验阶段201-2018.04.25)...
  • java8 Stream Pipelines 浅析
  • PHP 程序员也能做的 Java 开发 30分钟使用 netty 轻松打造一个高性能 websocket 服务...
  • REST架构的思考
  • Vue 动态创建 component
  • Web设计流程优化:网页效果图设计新思路
  • windows下如何用phpstorm同步测试服务器
  • 对象管理器(defineProperty)学习笔记
  • 记录:CentOS7.2配置LNMP环境记录
  • 面试题:给你个id,去拿到name,多叉树遍历
  • 使用SAX解析XML
  • 微信端页面使用-webkit-box和绝对定位时,元素上移的问题
  • 正则表达式小结
  • 智能合约Solidity教程-事件和日志(一)
  • 容器镜像
  • #我与Java虚拟机的故事#连载04:一本让自己没面子的书
  • ()、[]、{}、(())、[[]]等各种括号的使用
  • (4) openssl rsa/pkey(查看私钥、从私钥中提取公钥、查看公钥)
  • (Oracle)SQL优化技巧(一):分页查询
  • (附源码)计算机毕业设计ssm-Java网名推荐系统
  • (离散数学)逻辑连接词
  • (译)计算距离、方位和更多经纬度之间的点
  • (转)mysql使用Navicat 导出和导入数据库
  • (转)Spring4.2.5+Hibernate4.3.11+Struts1.3.8集成方案一
  • (转)真正的中国天气api接口xml,json(求加精) ...
  • (转载)PyTorch代码规范最佳实践和样式指南
  • .axf 转化 .bin文件 的方法
  • .bat批处理(八):各种形式的变量%0、%i、%%i、var、%var%、!var!的含义和区别
  • .NET 5种线程安全集合
  • .net 打包工具_pyinstaller打包的exe太大?你需要站在巨人的肩膀上-VC++才是王道
  • .Net 转战 Android 4.4 日常笔记(4)--按钮事件和国际化
  • .NET中统一的存储过程调用方法(收藏)
  • .sh
  • // an array of int
  • /boot 内存空间不够
  • /usr/bin/perl:bad interpreter:No such file or directory 的解决办法
  • [].shift.call( arguments ) 和 [].slice.call( arguments )
  • [autojs]autojs开关按钮的简单使用