[CUDA] 快速入门CUDA(1)-基本了解和HelloWorld

2023-11-19

CUDA基础

1 CUDA简介

CUDA的全程是Computer Unified Device Architecture,是由显卡头子NVIDIA发明的。有的人对于显卡的印象在于它可以玩游戏,效果十分逼真,但从背后而言,正是因为显卡强大的图形计算能力,才使得计算机可以运行这些大型的3D游戏,并且拥有较高的画质和帧数。

2 GPU和CPU架构的不同之处

CPU具有以下特点:

  • 对单线程有优化,运算速度快
  • 善于复杂的控制逻辑,预测等
  • 拥有很大的低延迟缓存来减少平均DRAM的访问时间

它的架构可以被表示为下图
CPU架构图
GPU则具有以下特点:

  • 核心被设计为执行大量的并行线程
  • 核心对于数据的并行计算有优化
  • 使用额外的多线程来优化DRAM的访问时间

它的架构图如下:
GPU架构图
除此之外,还需要知道GPU当中拥有许多流处理器(Streaming Multiprocessor),以及众多CUDA核心。

3 查看GPU硬件信息

默认已经配置好了相关的环境,本文将不再过多赘述,需要的朋友可以自行搜索,有很多的教程。本文均以Linux环境作为演示。

现在已经配置好了环境,那么就需要查看以下我们拥有的GPU硬件信息,这也方便于我们后期设置一些参数。使用以下例程,就可以查看GPU的硬件信息了。

#include <stdio.h>
#include <stdlib.h>
#include <cuda_runtime.h>

/**
 * @brief print device properties
 * 
 * @param prop 
 */
void showDeviceProp(cudaDeviceProp &prop) {
    printf("Device name: %s\n", prop.name);
    printf("  Compute capability: %d.%d\n", prop.major, prop.minor);
    printf("  Clock rate: %d\n", prop.clockRate);
    printf("  Memory clock rate: %d\n", prop.memoryClockRate);
    printf("  Memory bus width: %d\n", prop.memoryBusWidth);
    printf("  Peak memory bandwidth: %d\n", prop.memoryBusWidth);
    printf("  Total global memory: %lu\n", prop.totalGlobalMem);
    printf("  Total shared memory per block: %lu\n", prop.sharedMemPerBlock);
    printf("  Total registers per block: %d\n", prop.regsPerBlock);
    printf("  Warp size: %d\n", prop.warpSize);
    printf("  Maximum memory pitch: %lu\n", prop.memPitch);
    printf("  Maximum threads per block: %d\n", prop.maxThreadsPerBlock);
    printf("  Maximum dimension of block: %d x %d x %d\n", prop.maxThreadsDim[0], prop.maxThreadsDim[1], prop.maxThreadsDim[2]);
    printf("  Maximum dimension of grid: %d x %d x %d\n", prop.maxGridSize[0], prop.maxGridSize[1], prop.maxGridSize[2]);
    printf("  Maximum memory alloc size: %lu\n", prop.totalConstMem);
    printf("  Texture alignment: %lu\n", prop.textureAlignment);
    printf("  Concurrent copy and execution: %s\n", prop.deviceOverlap ? "Yes" : "No");
    printf("  Number of multiprocessors: %d\n", prop.multiProcessorCount);
    printf("  Kernel execution timeout: %s\n", prop.kernelExecTimeoutEnabled ? "Yes" : "No");
    printf("  Integrated GPU sharing Host Memory: %s\n", prop.integrated ? "Yes" : "No");
}

int main() {
    int num_devices;
    cudaDeviceProp properties;
    cudaGetDeviceCount(&num_devices);
    printf("%d CUDA devices found\n", num_devices);
    for (int i = 0; i < num_devices; i++) {
        cudaGetDeviceProperties(&properties, i);
        printf("Device %d: \"%s\"\n", i, properties.name);
        showDeviceProp(properties);
    }

    return 0;
}

编译该程序nvcc device_query.cu -o device_query,然后运行./device_query,就可以得到本机的硬件信息了。

1 CUDA devices found
Device 0: "NVIDIA Tesla K40c"
Device name: NVIDIA Tesla K40c
  Compute capability: 3.5
  Clock rate: 745000
  Memory clock rate: 3004000
  Memory bus width: 384
  Peak memory bandwidth: 384
  Total global memory: 11996954624
  Total shared memory per block: 49152
  Total registers per block: 65536
  Warp size: 32
  Maximum memory pitch: 2147483647
  Maximum threads per block: 1024
  Maximum dimension of block: 1024 x 1024 x 64
  Maximum dimension of grid: 2147483647 x 65535 x 65535
  Maximum memory alloc size: 65536
  Texture alignment: 512
  Concurrent copy and execution: Yes
  Number of multiprocessors: 15
  Kernel execution timeout: No
  Integrated GPU sharing Host Memory: No

可以看到是一块英伟达特斯拉K40显卡,计算能力为3.5,以及其他各种参数。看不懂也没有关系,因为不是特别重要,主要是检测一下是否成功配置了相关的环境。如果想看完整的参数,那需要增加更多的语句,并且打印对应的参数,完整参数列表可以在该网站找到英伟达API官网

4 需要建立的基本概念

代码被分成两部分,一部分是在CPU上,也称之为在Host上,另一部分是在GPU上,也称之为在device上。他们两者的关系如下图所示。
Host和Device的关系
程序开始运行时,先将数据通过总线传给GPU,由GPU运算完毕之后再回传给Host,由于数据传输耗费的时间取决于总线带宽,数据量的大小等因素,所以要尽量避免反复传递数据,这样很可能会出现GPU在等数据的时间比实际运算的时间长。

定义运行在GPU上的Code(核函数)

运行在GPU上的代码需要像下面这样声明
__global__ void mykernel(void) { // 要计算的内容}

  • __global__表示一个函数要在GPU上运行
  • 此函数遵循C语言的语法,也可以使用CUDA的扩展函数等
  • 核函数会从host上调用
  • nvcc会将host和device的部分分开来编译

网格grids和线程块blocks

网格grids,在上层,至多可以分成三维的blocks,在不同block当中的线程是不能通信的;线程块blocks在相对较低的层级,同样可以将线程分成三维,而在同一个块中的线程是可以通信的。

对于一个核函数,只能有一个grid,但是可以有多个block,之所以将线程划分为grid和block是为了使得结构更清晰,便于线程管理,灵活运用。

管理模型
上图是一个二维grid和二维block的模型示意图,引用了谭生的博客,他写的很好很全面,想要系统慢慢学习的推荐看他的。

调用核函数

调用核函数需要像如下,下面程序表示的模型就是上图所展示的,一个grid当中有6个block,一个block当中有15个线程。

#include <stdio.h>
#include <stdlib.h>
#include <cuda_runtime.h>

__global__ void mykernel(void) {
    int col_index = threadIdx.x + blockIdx.x * blockDim.x;
    int row_index = threadIdx.y + blockIdx.y * blockDim.y;
    printf("hello from (%d,%d) \n",row_index,col_index);
}

int main(void) {
    dim3 grid(2,3);
    dim3 block(3,5);
    mykernel<<<grid, block>>>();
    // synchronize the device
    cudaDeviceSynchronize();
}

编译nvcc grid_and_block.cu -o a.out之后,运行./a.out,可以观察到,终端中打印出了一共80个坐标,如下所示。

hello from (10,3) 
hello from (10,4) 
hello from (10,5) 
hello from (11,3) 
hello from (11,4) 
hello from (11,5) 
hello from (12,3) 
hello from (12,4) 
hello from (12,5) 
hello from (13,3) 
hello from (13,4) 
hello from (13,5) 
hello from (14,3) 
hello from (14,4) 
hello from (14,5) 
hello from (0,0) 
hello from (0,1) 
hello from (0,2) 
hello from (1,0) 
hello from (1,1) 
hello from (1,2) 
hello from (2,0) 
hello from (2,1) 
hello from (2,2) 
hello from (3,0) 
hello from (3,1) 
hello from (3,2) 
hello from (4,0) 
hello from (4,1) 
hello from (4,2) 
hello from (10,0) 
hello from (10,1) 
hello from (10,2) 
hello from (11,0) 
hello from (11,1) 
hello from (11,2) 
hello from (12,0) 
hello from (12,1) 
hello from (12,2) 
hello from (13,0) 
hello from (13,1) 
hello from (13,2) 
hello from (14,0) 
hello from (14,1) 
hello from (14,2) 
hello from (5,0) 
hello from (5,1) 
hello from (5,2) 
hello from (6,0) 
hello from (6,1) 
hello from (6,2) 
hello from (7,0) 
hello from (7,1) 
hello from (7,2) 
hello from (8,0) 
hello from (8,1) 
hello from (8,2) 
hello from (9,0) 
hello from (9,1) 
hello from (9,2) 
hello from (5,3) 
hello from (5,4) 
hello from (5,5) 
hello from (6,3) 
hello from (6,4) 
hello from (6,5) 
hello from (7,3) 
hello from (7,4) 
hello from (7,5) 
hello from (8,3) 
hello from (8,4) 
hello from (8,5) 
hello from (9,3) 
hello from (9,4) 
hello from (9,5) 
hello from (0,3) 
hello from (0,4) 
hello from (0,5) 
hello from (1,3) 
hello from (1,4) 
hello from (1,5) 
hello from (2,3) 
hello from (2,4) 
hello from (2,5) 
hello from (3,3) 
hello from (3,4) 
hello from (3,5) 
hello from (4,3) 
hello from (4,4) 
hello from (4,5)

5 总结

今天主要是大致了解了一下CUDA是什么,以及最基本的需要建立的概念,然后给出了核函数使用的例子。明天继续更新!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

[CUDA] 快速入门CUDA(1)-基本了解和HelloWorld 的相关文章

随机推荐

  • ChatGPT也不会的k8s安装方法——极简安装法

    要学习k8s 首先要有一个k8s 那么如何才能获得一个k8s呢 这不由得让我想到了最近比较火的ChatGPT 以下简称小恰 俗话说 遇事不决问小恰 解决效率翻上翻 让我们先来看看小恰怎么回答的吧 问小恰 由于众所周知的原因 国内使用小恰比较
  • 【Hyperledger Fabric 源码解读】solo

    release 2 2 orderer consensus solo consensus go Copyright IBM Corp All Rights Reserved SPDX License Identifier Apache 2
  • 持久化RDB/AOF-Redis(三)

    上篇文章说了数据持久化 这里再学习一个命令 数据结构 Redis 二 https blog csdn net ke1ying article details 131118016 一 查询所有key scan 0 match zhuge co
  • 【动态规划】从入门到实践---动态规划详解

    目录 1 动态规划概念 一 定义数组元素的含义 二 找到数组元素之间的关系表达式 三 找到初始值 2 案例详解 一 爬楼梯 1 定义数组元素的含义 2 找到数组元素之间的关系表达式 3 找到初始值 案例二 最短路径 题目 做题步骤 1 定义
  • eclipse项目上出现两个红点(类似两个红心)的标志

    找了老久 浪费光阴 肯定引用的jar包有问题 大不了重新引用一下
  • 基于内容的图像检索系统设计与实现--颜色信息--纹理信息--形状信息--PHASH--SHFT特征点的综合检测项目,包含简易版与完整版的源码及数据!

    百度云提取源码以及数据包 直接下载压缩包解压就可以使用 数据就在压缩包文件dataset中 简化版 只有 颜色信息 纹理信息 形状信息 PHASH SHFT特征点的综合检测 百度云链接 提取码 6666 戳我 完整版 包含只有 颜色信息 纹
  • python3 字符串format 输出

    gt gt gt help FORMATING Traceback most recent call last File
  • 潜艇来袭(Qt官方案例-2维动画游戏)

    一 游戏介绍 1 开始界面 启动程序 进入开始界面 2 开始新游戏 点击菜单 File New Game 或者Ctrl N 进入新游戏 开始新游戏之后 会有一个海底的潜艇 和水面舰艇对战 计算机 自动控制潜艇 海底潜艇会隔段时间发射一枚鱼雷
  • Node输出日志的正确姿势

    背景 每个程序员都喜欢在有问题的代码中插入一些日志的方法来帮助调试程序 比如System out println或console log 解决后 就会将这些语句删除 周而复始 但是通过系统日志输出的日志格式都是这种 output conso
  • Android加载webView--setWebChromeClient默认不会显示弹窗

    1 设置自定义浏览器客户端 webView setWebChromeClient new MyWebChromeClient 2 onJsAlert就是弹窗 只会有一个 自定义弹出框 class MyWebChromeClient exte
  • VSCode关闭vue语法检查

    今天碰到一个这样的错误 Component name School should always be multi word 意思是组件名称 School 应该总是多个单词 解决办法 在vue config js中添加这样一句代码 lintO
  • QT实现动态翻译和语言切换

    QT GUI提供语言动态转换机制并辅以相应的工具方便programmer实现界面的多语言实时动态切换功能 实现语言动态切换的方法 一个注意 五个步骤 一个注意 实现QT工程的语言切换功能的一个关键点是所有的字符串都需要tr修饰符 例如 m
  • 【数据结构初阶】第七节.树和二叉树的基本操作

    作者简介 大家好 我是未央 博客首页 未央 303 系列专栏 Java初阶数据结构 每日一句 人的一生 可以有所作为的时机只有一次 那就是现在 文章目录 前言 一 二叉树的快速构建 二 二叉树的遍历 2 1 前序遍历 2 2 中序遍历 2
  • 从计数器到分频电路

    一 计数器 1 计数器代码 计数器 顾名思义就是在时钟的节拍下进行计数 一个简单的N位计数器的代码如下所示 这个计数器从0计数到2 N 1 共计数了2 N个数 也就是N位计数器 1 module count parameter N 8 2
  • 微信小程序登录弹框问题

    1 getUserInfo 相信刚接触微信小程序开发的人都在想 官方给出的这个是什么意思 我来解释一下吧 还记得我们在最开始使用微信小程序的时候吗 第一次进一个微信小程序的时候会直接弹出来个框 询问我们是否允许哟用户获取信息 微信官方觉得这
  • C++11 之 std::function & std::bind & lambda 表达式

    文章目录 std function std bind lambda 表达式 总结 c 11新增了 std function std bind lambda 表达式等封装使函数调用更加方便 std function 讲 std functio
  • 生活之你为什么不学习

    最近在别人的空间 我看到了八句话 你有什么理由不学习 感觉说得挺有鸡血的 1 你不能把这个世界让给你所鄙视的人 2 成功的速度一定要超过父母老去的速度 3 可怕的不是别人比你优秀 而是比你优秀的人比你还努力 4 我努力的目的是让我的妈妈买东
  • 【华为OD机试python】按身高和体重排队【2023 B卷

    华为OD机试 真题 点这里 华为OD机试 真题考点分类 点这里 题目描述 某学校举行运动会 学生们按编号 1 2 3 n 进行标识 现需要按照身高由低到高排列 对身高相同的人 按体重由轻到重排列 对于身高体重都相同的人 维持原有的编号顺序关
  • 最全的交叉编译Makefile讲解

    最近正在搞交叉编译 参考很多博客 学习了一下Makefile的编写 记录一下Makefile内代码是什么意思 代码如下 简单的hello ko的makefile ifneq KERNELRELEASE obj m hello o else
  • [CUDA] 快速入门CUDA(1)-基本了解和HelloWorld

    CUDA基础 文章目录 CUDA基础 1 CUDA简介 2 GPU和CPU架构的不同之处 3 查看GPU硬件信息 4 需要建立的基本概念 5 总结 1 CUDA简介 CUDA的全程是Computer Unified Device Archi