CUDA与TensorRT学习二:CUDA编程入门

news2024/11/28 18:43:43

文章目录

    • 一、理解CUDA的grid和Block
      • 1)第一个cuda项目
    • 二、理解.cu和.cpp的相互引用及Makefile
    • 三、利用CUDA矩阵乘法(matmul)计算、Error Handle 及硬件信息获取
      • 1)矩阵乘法
      • 2)Error Handle
      • 3)硬件信息获取
    • 四、安装Nsight system and compute
    • 五、共享内存、Bank Conflict原因和解决方法、TRT用Cuda进行预处理/后处理来加速、Stream 与Event(用Cuda写流提高并发性)
    • 六、双线性插值与仿射变换

一、理解CUDA的grid和Block

  • 目标
    理解Cuda中一维、二维、三维的grid、block的写法,以及遍历thread的方法

1)第一个cuda项目

  • 修改项目的Makefile.config
    在这里插入图片描述
  • 总体文件目录
    在这里插入图片描述
  • 代码
#include <cuda_runtime.h>
#include <stdio.h>


__global__ void print_idx_kernel(){
    printf("block idx: (%3d, %3d, %3d), thread idx: (%3d, %3d, %3d)\n",
         blockIdx.z, blockIdx.y, blockIdx.x,
         threadIdx.z, threadIdx.y, threadIdx.x);
}

__global__ void print_dim_kernel(){
    printf("grid dimension: (%3d, %3d, %3d), block dimension: (%3d, %3d, %3d)\n",
         gridDim.z, gridDim.y, gridDim.x,
         blockDim.z, blockDim.y, blockDim.x);
}

__global__ void print_thread_idx_per_block_kernel(){
    int index = threadIdx.z * blockDim.x * blockDim.y + \
              threadIdx.y * blockDim.x + \
              threadIdx.x;

    printf("block idx: (%3d, %3d, %3d), thread idx: %3d\n",
         blockIdx.z, blockIdx.y, blockIdx.x,
         index);
}

__global__ void print_thread_idx_per_grid_kernel(){
    int bSize  = blockDim.z * blockDim.y * blockDim.x;

    int bIndex = blockIdx.z * gridDim.x * gridDim.y + \
               blockIdx.y * gridDim.x + \
               blockIdx.x;

    int tIndex = threadIdx.z * blockDim.x * blockDim.y + \
               threadIdx.y * blockDim.x + \
               threadIdx.x;

    int index  = bIndex * bSize + tIndex;

    printf("block idx: %3d, thread idx in block: %3d, thread idx: %3d\n", 
         bIndex, tIndex, index);
}

__global__ void print_cord_kernel(){
    int index = threadIdx.z * blockDim.x * blockDim.y + \
              threadIdx.y * blockDim.x + \
              threadIdx.x;

    int x  = blockIdx.x * blockDim.x + threadIdx.x;
    int y  = blockIdx.y * blockDim.y + threadIdx.y;

    printf("block idx: (%3d, %3d, %3d), thread idx: %3d, cord: (%3d, %3d)\n",
         blockIdx.z, blockIdx.y, blockIdx.x,
         index, x, y);
}

void print_one_dim(){
    int inputSize = 8;
    int blockDim = 4;
    int gridDim = inputSize / blockDim;

    dim3 block(blockDim);
    dim3 grid(gridDim);

    /* 这里建议大家吧每一函数都试一遍*/
    // print_idx_kernel<<<grid, block>>>();
    // print_dim_kernel<<<grid, block>>>();
    // print_thread_idx_per_block_kernel<<<grid, block>>>();
    print_thread_idx_per_grid_kernel<<<grid, block>>>();

    cudaDeviceSynchronize();
}

void print_two_dim(){
    int inputWidth = 4;

    int blockDim = 2;
    int gridDim = inputWidth / blockDim;

    dim3 block(blockDim, blockDim);
    dim3 grid(gridDim, gridDim);

    /* 这里建议大家吧每一函数都试一遍*/
    // print_idx_kernel<<<grid, block>>>();
    // print_dim_kernel<<<grid, block>>>();
    // print_thread_idx_per_block_kernel<<<grid, block>>>();
    print_thread_idx_per_grid_kernel<<<grid, block>>>();

    cudaDeviceSynchronize();
}

void print_cord(){
    int inputWidth = 4;

    int blockDim = 2;
    int gridDim = inputWidth / blockDim;

    dim3 block(blockDim, blockDim);
    dim3 grid(gridDim, gridDim);

    print_cord_kernel<<<grid, block>>>();

    cudaDeviceSynchronize();
}

int main() {
    /*
    synchronize是同步的意思,有几种synchronize

    cudaDeviceSynchronize: CPU与GPU端完成同步,CPU不执行之后的语句,知道这个语句以前的所有cuda操作结束
    cudaStreamSynchronize: 跟cudaDeviceSynchronize很像,但是这个是针对某一个stream的。只同步指定的stream中的cpu/gpu操作,其他的不管
    cudaThreadSynchronize: 现在已经不被推荐使用的方法
    __syncthreads:         线程块内同步
    */
    // print_one_dim();
    // print_two_dim();
    print_cord();
    return 0;
}

  • 注意
    __global__ 表示核函数kernel

  • 需求:找到某个block下面的thread
    在这里插入图片描述

代码如下(先走z,然后y,最后z)
在这里插入图片描述
一般的优化
在这里插入图片描述

二、理解.cu和.cpp的相互引用及Makefile

  • 编译器
    不再是gcc或g++,而是nvcc,这样才不会编译报错
  • 编译项目一指令
nvcc print_index.cu  -o app -I  /usr/local/cuda/include/
  • cuda_check作用
    发生错误的时候告诉你错误发生在哪里
#define CUDA_CHECK(call) {                                                 \
    cudaError_t error = call;                                              \
    if (error != cudaSuccess) {                                            \
        printf("ERROR: %s:%d, ", __FILE__, __LINE__);                      \
        printf("CODE:%d, DETAIL:%s\n", error, cudaGetErrorString(error));  \
        exit(1);                                                           \
    }                                                                      \
}

三、利用CUDA矩阵乘法(matmul)计算、Error Handle 及硬件信息获取

1)矩阵乘法

  • 目的
    理解使用cuda进行矩阵运算的加速方法,tile的用意
  • 项目目录
    在这里插入图片描述

2)Error Handle

  • 项目目录
    在这里插入图片描述

3)硬件信息获取

  • 目标
    学习使用cuda runtime api显示GPU硬件信息,以及理解GPU硬件信息重要性
  • 项目布局
    在这里插入图片描述
  • 打印效果
    在这里插入图片描述
  • 相关代码
int main(){
    int count;
    int index = 0;
    cudaGetDeviceCount(&count);
    while (index < count) {
        cudaSetDevice(index);
        cudaDeviceProp prop;
        cudaGetDeviceProperties(&prop, index);
        LOG("%-40s",             "*********************Architecture related**********************");
        LOG("%-40s%d%s",         "Device id: ",                   index, "");
        LOG("%-40s%s%s",         "Device name: ",                 prop.name, "");
        LOG("%-40s%.1f%s",       "Device compute capability: ",   prop.major + (float)prop.minor / 10, "");
        LOG("%-40s%.2f%s",       "GPU global meory size: ",       (float)prop.totalGlobalMem / (1<<30), "GB");
        LOG("%-40s%.2f%s",       "L2 cache size: ",               (float)prop.l2CacheSize / (1<<20), "MB");
        LOG("%-40s%.2f%s",       "Shared memory per block: ",     (float)prop.sharedMemPerBlock / (1<<10), "KB");
        LOG("%-40s%.2f%s",       "Shared memory per SM: ",        (float)prop.sharedMemPerMultiprocessor / (1<<10), "KB");
        LOG("%-40s%.2f%s",       "Device clock rate: ",           prop.clockRate*1E-6, "GHz");
        LOG("%-40s%.2f%s",       "Device memory clock rate: ",    prop.memoryClockRate*1E-6, "Ghz");
        LOG("%-40s%d%s",         "Number of SM: ",                prop.multiProcessorCount, "");
        LOG("%-40s%d%s",         "Warp size: ",                   prop.warpSize, "");

        LOG("%-40s",             "*********************Parameter related************************");
        LOG("%-40s%d%s",         "Max block numbers: ",           prop.maxBlocksPerMultiProcessor, "");
        LOG("%-40s%d%s",         "Max threads per block: ",       prop.maxThreadsPerBlock, "");
        LOG("%-40s%d:%d:%d%s",   "Max block dimension size:",     prop.maxThreadsDim[0], prop.maxThreadsDim[1], prop.maxThreadsDim[2], "");
        LOG("%-40s%d:%d:%d%s",   "Max grid dimension size: ",     prop.maxGridSize[0], prop.maxGridSize[1], prop.maxGridSize[2], "");
        index ++;
        printf("\n");
    }
    return 0;
}
  • 知道参数的重要性
    很多时候编译.cu代码需要在nvcc之后加上编译信息,就需要打印GPU信息出来方便编译(比如共享内存的使用对cuda程序的加速很重要,可以动态修改共享内存和L1 Cache,而且知道作为调度thread的warp是由多少个thread组成的,也可以提高利用率)

四、安装Nsight system and compute

五、共享内存、Bank Conflict原因和解决方法、TRT用Cuda进行预处理/后处理来加速、Stream 与Event(用Cuda写流提高并发性)

六、双线性插值与仿射变换

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【APP自动化】Appium 环境搭建

1 基础环境 安装 node.js (1) 安装node.js 安装的是10版本&#xff0c;node-v10.16.0-x64&#xff0c;node.js安装比较简单&#xff0c;直接采用默认选项即可&#xff0c;路径的话&#xff0c;可以自己更改下。 (2) 添加Path环境变量 (3) 验证node.js是否安装成功 可以在CMD…

STM32 IIC

第一块&#xff1a;介绍协议规则&#xff0c;然后用软件模拟的形式来实现协议&#xff0c; 第二块&#xff1a;介绍STM32的IIC外设&#xff0c;然后用硬件来实现协议 因为IIC是同步时序的额&#xff0c;软件模拟协议也非常方便&#xff0c;像我们单片机一样&#xff0c;外挂芯…

零基础入门转录组数据分析——基因Wilcoxon秩和检验

零基础入门转录组数据分析——基因Wilcoxon秩和检验 目录 零基础入门转录组数据分析——基因Wilcoxon秩和检验1. 单基因Wilcoxon秩和检验的基础知识2. 基因Wilcoxon秩和检验&#xff08;Rstudio&#xff09;——代码实操2. 1 数据处理2. 2 基因Wilcoxon秩和检验2. 3 Wilcoxon秩…

FreeRTOS学习笔记—①堆与栈

在嵌入式系统中&#xff0c;堆与栈通常表示操作系统对进程占用的两种管理方式&#xff0c;而RTOS中栈更为重要&#xff0c;每一个链路都要有自己的栈。因此对堆和栈的概念进行了些区分和了解。以下是自己学习总结的一些&#xff0c;如有不对的地方请指正&#xff1a; &#xf…

算法打卡 Day25(二叉树)-修剪二叉搜索树 + 将有序数组转换为二叉搜索树 + 把二叉搜索树转换为累加树

文章目录 Leetcode 669-修剪二叉搜索树题目描述解题思路 Leetcode 108-将有序数组转换为二叉搜索树题目描述解题思路 Leetcode 538-把二叉搜索树转换为累加树题目描述解题思路 Leetcode 669-修剪二叉搜索树 题目描述 https://leetcode.cn/problems/trim-a-binary-search-tree…

elementUI——checkbox复选框监听不到change事件,通过watch监听来解决——基础积累

今天在写后台管理系统的时候&#xff0c;遇到一个需求&#xff0c;就是要求监听复选框的change事件&#xff0c;场景就是&#xff1a;两个复选框互斥&#xff0c;且可以取消勾选。 就是这两个复选框可以同时都不勾选&#xff0c;如果勾选的话&#xff0c;另一个一定要取消勾选。…

​如何通过Kimi强化论文写作中的数据分析?

在学术研究领域&#xff0c;数据分析是验证假设、发现新知识和撰写高质量论文的关键环节。Kimi&#xff0c;作为一款先进的人工智能助手&#xff0c;能够在整个论文写作过程中提供支持&#xff0c;从文献综述到数据分析&#xff0c;再到最终的论文修订。本文将详细介绍如何将Ki…

OceanBase 的ODP OBproxy 的记录

OceanBase 的ODP的路由说明一、简述为什么使用ODP的原因 &#xff08;强一致性情况下&#xff09; 1.分布式数据库在SQL解析这块存在本地执行计划&#xff0c;远程执行计划&#xff0c;分布式执行计划。 本地执行计划&#xff1a;整个SQL的表都在session所在的Observer 节点上。…

ABAP 结构体变量的嵌套INCLUDE TYPE 和 INCLUDE STRUCTURE

文章目录 创建程序语法格式程序测试AS SPFLI_NAME2 RENAMING WITH SUFFIX _NAME2 后缀变量的结构程序结构类型嵌套表和结构字段类型TYPES嵌套类型程序 创建程序 语法格式 程序测试 AS SPFLI_NAME2 RENAMING WITH SUFFIX _NAME2 后缀 变量的结构 程序 *&------------------…

Java进阶13讲__第六讲

算法&#xff1a; 冒泡排序 选择排序 二分查找 1. 冒泡排序 1.1 定义 1.2 代码示例 Java业务逻辑-1(冒泡排序)-CSDN博客https://blog.csdn.net/XiaomeiGuiSnJs/article/details/140880229 2. 选择排序 2.1 定义 2.2 代码示例 package cn.hdc.itWork.d5.d2;import java.uti…

【C语言】详解数组

文章目录 前言一、数组的概念二、一维数组1.一维数组的创建2.一维数组的初始化3. 一维数组的使用4.一维数组在内存中的存储 三、二维数组1.二维数组的创建2. 二维数组的初始化3. 二维数组的使用4.二维数组在内存中的存储 前言 一、数组的概念&#xff08;数组是一组相同类型元素…

精准设计与高效开发:用六西格玛设计DFSS实现新能源汽车开发突破

快速变化的市场需求和激烈的竞争迫使制造企业不得不持续创新和优化产品开发流程。如何在保证产品质量的前提下&#xff0c;加快产品开发周期&#xff0c;成为许多企业亟待解决的问题。六西格玛中的DFSS&#xff08;Design for Six Sigma&#xff09;模型提供了一种系统的方法&a…

维信小程序禁止截屏/录屏

一、维信小程序禁止截屏/录屏 //录屏截屏,禁用wx.setVisualEffectOnCapture({visualEffect:hidden});wx.setVisualEffectOnCapture(Object object) 测试安卓手机&#xff1a; 用户截屏&#xff0c;被禁用 用户录屏&#xff0c;录制的是空白内容/黑色内容的视频。 二、微信小…

RS-FS-N01风速变送器简明教程(485通信类型变送器)

该文章仅供参考&#xff0c;编写人不对任何实验设备、人员及测量结果负责&#xff01;&#xff01;&#xff01; 文章主要介绍变送器的硬件连接、软件配置、数据读写以温湿度计算。 1 硬件连接 2 软件配置 将变送器硬件部分正确连接后 打开“485 参数配置工具.exe” 对风速…

hello树先生——红黑树

红黑树 一.什么是红黑树二.红黑树的实现1.创建树节点结构2.插入功能的实现 三.提供一些常见二叉树接口四.进行平衡测试 一.什么是红黑树 红黑树是一种自平衡的二叉搜索树&#xff0c;具有以下特性&#xff1a; 节点颜色&#xff1a;每个节点要么是红色&#xff0c;要么是黑色。…

从模型到实践:新时代【数学建模竞赛论文】的结构、规范与创新解析

目录 1. 数学建模竞赛论文的重要作用 1.1 论文是竞赛成果的书面形式 1.2 论文是评判参赛成绩的唯一依据 1.3 论文写作是科技论文写作的基本训练 1.4 数学建模竞赛论文的综合性 1.5 数学建模竞赛论文与学术研究的联系 1.6 数学建模竞赛论文的重要性在评委眼中 1.7 数学建…

Leetcode3248. 矩阵中的蛇

Every day a Leetcode 题目来源&#xff1a;3248. 矩阵中的蛇 解法1&#xff1a;模拟 遍历字符串数组 commands&#xff0c;模拟&#x1f40d;的移动过程。 如果最后&#x1f40d;的位置为 (i, j)&#xff0c;则编号为 (i * n) j。 代码&#xff1a; /** lc appleetcode…

[Hive]五、Hive 源码编译

G:\Bigdata\2.hive\大数据技术之Hive源码编译 第1章 部署Hadoop和Hive 1.1 版本测试 Hadoop3.3.6 和Hive3.1.3 运行hive客户端时报错: java.lang.NoSuchMethodError:com.google.common.base.Preconditions.checkArgument(ZLjava/lang/String;Ljava/lang/Object;)V 查看Ha…

计算机的错误计算(八十一)

摘要 讨论双曲正弦函数 sinh(x)的计算精度问题。 例1. 计算 sinh(312.08) . 若在Python下计算&#xff0c;则有&#xff1a; 若在Excel单元格中计算&#xff0c;则有&#xff1a; 事实上&#xff0c;16位的正确值是 0.1712347549914620e136&#xff08;ISRealsoft 提供&…

MLLM(一)| 文/图生视频任务大升级,BigModel 开源了视频模型CogVideoX

CogVideoX的体验地址&#xff1a;https://bigmodel.cn/console/trialcenter?modelCodecogvideox 自2021年起&#xff0c;智谱 AI 技术团队便开始着手布局包括 text-2-img、text-2-video、img-2-text、video-2-text 在内的多模态模型&#xff0c;并陆续研发并开源了CogView、Co…