Nvidia CUDA初级教程7 CUDA编程二

Nvidia CUDA初级教程7 CUDA编程二

视频:https://www.bilibili.com/video/BV1kx411m7Fk?p=8
讲师:周斌

本节内容:

  • 内置类型和函数 Built-ins and functions
  • 线程同步 Synchronizing
  • 线程调度 Scheduling threads
  • 存储模型 Memory model
  • 重访 Matrix multiply
  • 原子函数 Atomic functions

函数的声明

执行调用
__global__ void KernelFunc()devicehost
__device__ float DeviceFunc()devicedevice
__host__ float Hosthosthost
  • __device____host__ 可以同时修饰一个函数
  • __global__ 的返回值必须是 void
  • __device__ 曾经默认内联,现在有些变化
  • 对于 global 和 device:
    • 尽量少用递归(不鼓励)
    • 不要用静态变量
    • 少用 malloc(现在允许但不鼓励)
    • 小心通过指针实现函数调用

向量数据类型

  • char[1-4], uchar[1-4]
  • short[1-4], ushort[1-4]
  • int[1-4], uint[1-4]
  • long[1-4], ulong[1-4]
  • longlong[1-4], ulonglong[1-4]
  • float[1-4]
  • double1, double2

  • 同时适用于 host 和 device 代码

  • 通过函数 make_<type name> 构造

    int2 i2 = make_int2(1, 2);
    float4 f4 = make_float4(1.0f, 2.0f, 3.0f, 4.0f);
    
  • 通过 .x, .y, .z, ,w 访问

    int x = i2.x;
    int y = i2.y;
    

数学函数

  • 部分函数列表

    • sqrt, rsqrt
    • exp, log
    • sin, cos, tan, sincos
    • asin, acos, atan2
    • trunc, ceil, floor
  • Intrinsic function 内建函数

    • 仅面向 device 设备端

    • 更快,但是精度降低

    • __ 为前缀,例如:

      __exp, __log, __sin, __pow, …

线程层次回顾

线程同步

  • 块内的线程可以同步
    • 调用 __syncthreads 创建一个 barrier
    • 每个线程在调用点等待块内所有线程执行到这个地方,然后所有线程继续执行后续指令
Mds[i] = Md[j];
__syncthreads();
func(Mds[i], Mds[i+1]);
  • 要求线程的执行时间尽量接近

  • 只在一个块内进行同步

  • 线程同步可能会导致死锁

    if (someFunc()) {__syncthreads();
    }
    else {__syncthreads();	// 注意这两个barrier不是同一个
    }
    

    线程调度

在这里插入图片描述

  • 多线程切换,达到延迟掩藏的效果。

  • warp - 块内的一组线程

    • 运行于同一个SM

    • 线程调度的基本单位

    • 一个warp内是天然同步的(硬件保证)

    • warp 调度是零开销的

    • 一个SM上某个时刻只会有一个warp再执行

    • threadIdx 值连续

    • 一个实现细节 - 理论上

      • warpSize
    • warp内执行不同的分支的情况:divergent warp

      其他的分支需要等待该分支进行

在这里插入图片描述

举例:

  • 如果一个 SM 分配了 3 个 block,其中每个 block 含 256 个线程,总共有多少个 warp(warp大小为32)?

    一个 block 内有 256/32 = 8个 warp,一个 SM 内共有 8 * 3 = 24个

  • GT200 的一个 SM 最多可以驻扎 1024 个线程,那相当于多少个 warp?

    1024 / 32 = 32

每个 warp 含 32 个小牛橙,但是每个 SM 只有 8 个 SPs,如何分配?

当一个 SM 调度一个 warp 时:

  • 指令已经预备
  • 在第一个周期 8 个线程进入 SPs
  • 在第二三四个周期也分别进入 8 个线程
  • 因此,分发一个 warp 需要4个周期

另一个问题:

一个 kernel 包含:

  • 1 次对 global memory 的读操作(200 cycles)
  • 4 次独立的 multiples/adds 操作

需要多少个 warp 才可以隐藏内存延迟?

解:

每个 warp 含 4 个 multiple/adds 操作需要16 个周期,我们需要覆盖 200 个周期,200 / 16 = 12.5 ,ceil(12.5)=13,需要 13 个 warps。

内存模型回顾

内存模型

寄存器 registers - G80

  • 每个 SM,多达 768 个 threads,8K 个寄存器,即每个线程可以分到 8K / 768 = 10 个寄存器

  • 超出限制后,线程数将因为 block 的减少而减少

    因为同一个 block 必须在同一个 SM 内

    例如,每个线程用到 11 个寄存器,而由于每个 block 含 256 个线程,则:

    • 一个 SM 可以驻扎多少个线程?512(两个block)
    • 一个 SM 可以驻扎多少个 warp? 16
    • warp 数少了意味着什么?效率降低

local memory

  • 存储于 global memory,作用域是每个 thread
  • 用于存储自动变量数组,通过常量索引访问

shared memory

  • 每个块
  • 快速,片上,可读写
  • 全速随机访问

global memory

  • 长延迟(100个周期)
  • 片外,可读写
  • 随机访问影响性能
  • host 主机端可读写

constant memory

  • 短延时,高带宽,当所有线程访问同一位置时只读
  • 存储于 global memory,但是有缓存
  • host 主机端可读写
  • 容量:64KB

变量声明

变量声明存储器作用域生命期
必须是单独的自动变量而不能是数组registerthreadkernel
自动变量数组localthreadkernel
__shared__ int sharedVar;sharedblockkernel
__device__ int globalVar;globalgridapplication
__constant__ int constantVarconstantgridapplication

关于 global and constant 变量

  • Host 可以通过以下函数访问:
    • cudaGetSymbolAddress()
    • cudaGetSymbolSize()
    • cudaMemcpyToSymbol()
    • cudaMemcpyFromSymbol()
  • constants 变量必须在函数外声明

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

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

相关文章

详解优酷视频质量评价体系

万字长文 | 详解优酷视频质量评价体系 分享嘉宾&#xff5c;李静博士&#xff0c;阿里巴巴文娱集团资深算法专家&#xff0c;阿里巴巴大文娱摩酷实验室视频体验与质量团队负责人 整理出品&#xff5c;AICUG人工智能社区 本文地址&#xff1a;https://www.6aiq.com/article/1617…

视频质量评价:挑战与机遇

视频质量评价&#xff1a;挑战与机遇 转自&#xff1a;https://zhuanlan.zhihu.com/p/384603663 本文整理自鹏城实验室助理研究员王海强在LiveVideoStack线上分享上的演讲。他通过自身的实践经验&#xff0c;详细讲解了视频质量评价的挑战与机遇。 文 / 王海强 整理 / LiveVi…

关于二分法的边界问题及两种写法

关于二分法的边界问题及两种写法 二分查找法大家很熟悉了&#xff0c;对于一个有序序列&#xff0c;我们可以通过二分查找法在 O(logN)O(logN)O(logN) 的时间内找到想要的元素。但是&#xff0c;在代码实现的过程中&#xff0c;如果没有仔细理解清楚&#xff0c;二分法的边界条…

Segmentaion标签的三种表示:poly、mask、rle

Segmentaion标签的三种表示&#xff1a;poly、mask、rle 不同于图像分类这样比较简单直接的计算机视觉任务&#xff0c;图像分割任务&#xff08;又分为语义分割、实例分割、全景分割&#xff09;的标签形式稍为复杂。在分割任务中&#xff0c;我们需要在像素级上表达的是一张…

Ubuntu PPA 使用指南

Ubuntu PPA 使用指南 转自&#xff1a;https://zhuanlan.zhihu.com/p/55250294 一篇涵盖了在 Ubuntu 和其他 Linux 发行版中使用 PPA 的几乎所有问题的深入的文章。 如果你一直在使用 Ubuntu 或基于 Ubuntu 的其他 Linux 发行版&#xff0c;例如 Linux Mint、Linux Lite、Zorin…

杨宏宇:腾讯多模态内容理解技术及应用

杨宏宇&#xff1a;腾讯多模态内容理解技术及应用 分享嘉宾&#xff1a;杨宇鸿 腾讯 内容理解高级工程师 编辑整理&#xff1a;吴祺尧 出品平台&#xff1a;DataFunTalk 导读&#xff1a; 搜索内容的理解贯穿了整个搜索系统。我们需要从多个粒度理解搜索内容&#xff0c;包括语…

CUDA环境详解

CUDA环境详解 本文主要介绍 CUDA 环境&#xff0c;这一堆东西网上有很多博客介绍过了&#xff0c;我再来一篇:)&#xff0c;参考前辈们的文章&#xff0c;看能不能写的更清楚一点。读后仍有问题&#xff0c;欢迎留言交流。 CUDA APIs CUDA是由NVIDIA推出的通用并行计算架构&…

对Docker镜像layer的理解

对Docker镜像layer的理解 转自&#xff1a;https://blog.csdn.net/u011069294/article/details/105583522 FROM python:3.6.1-alpine RUN pip install flask CMD [“python”,“app.py”] COPY app.py /app.py上面是一个Dockerfile的例子&#xff0c;每一行都会生成一个新的l…

机器学习系统:设计与实现 计算图

机器学习系统:设计与实现 计算图 转自&#xff1a;https://openmlsys.github.io/chapter_computational_graph/index.html 在上一章节中&#xff0c;我们展示了用户利用机器学习框架所编写的程序。这些用户程序包含了对于训练数据&#xff0c;模型和训练过程的定义。然而为了…

常见浮点数格式梳理

常见浮点数格式梳理 IEEE 754 标准 浮点数转换网站&#xff1a;https://www.h-schmidt.net/FloatConverter/IEEE754.html IEEE二进制浮点数算术标准&#xff0c;为许多CPU与浮点运算器所采用。这个标准定义了表示浮点数的格式&#xff08;包括负零-0&#xff09;与反常值&am…

混合精度训练

混合精度训练 转自&#xff1a;https://zhuanlan.zhihu.com/p/441591808 通常我们训练神经网络模型的时候默认使用的数据类型为单精度FP32。近年来&#xff0c;为了加快训练时间、减少网络训练时候所占用的内存&#xff0c;并且保存训练出来的模型精度持平的条件下&#xff0…

C++面试常考题——编译内存相关

C面试常考题——编译内存相关 转自&#xff1a;https://leetcode-cn.com/leetbook/read/cpp-interview-highlights/e4ns5g/ C程序编译过程 编译过程分为四个过程&#xff1a;编译&#xff08;编译预处理、编译、优化&#xff09;&#xff0c;汇编&#xff0c;链接。 编译预处…

关键字库函数

关键字库函数 转自&#xff1a;https://leetcode-cn.com/leetbook/read/cpp-interview-highlights/ej3mx1/ sizeof和strlen的区别 strlen 是头文件<cstring> 中的函数&#xff0c;sizeof 是 C 中的运算符。 strlen 测量的是字符串的实际长度&#xff08;其源代码如下&…

memcpy和memmove的区别以及内存重叠问题

memcpy和memmove的区别以及内存重叠问题 转自&#xff1a;https://www.codecomeon.com/posts/89/ 区别 memcpy() 和 memmove() 都是C语言中的库函数&#xff0c;在头文件 string.h 中&#xff0c;作用是拷贝一定长度的内存的内容&#xff0c;原型分别如下&#xff1a; void…

从头搭建一个深度学习框架

从头搭建一个深度学习框架 转自&#xff1a;Build a Deep Learning Framework From Scratch 代码&#xff1a;https://github.com/borgwang/tinynn 当前深度学习框架越来越成熟&#xff0c;对于使用者而言封装程度越来越高&#xff0c;好处就是现在可以非常快速地将这些框架作为…

Docker概念理解

Docker概念理解 本文非Docker命令大全&#xff0c;而是对Docker的概念、原理等作说明&#xff0c;适合有一定实操经验后来加深理解。 转自&#xff1a;docker从入门到实践 Docker简介 本章将带领你进入 Docker 的世界。 什么是 Docker&#xff1f; 用它会带来什么样的好处&a…

Linux内存背后的那些神秘往事

Linux内存背后的那些神秘往事 作者&#xff1a;大白斯基&#xff08;公众号&#xff1a;后端研究所&#xff09; 转自&#xff1a;https://mp.weixin.qq.com/s/l_YdpyHht5Ayvrc7LFZNIA 前言 大家好&#xff0c;我的朋友们&#xff01; CPU、IO、磁盘、内存可以说是影响计算机…

精简CUDA教程——CUDA Driver API

精简CUDA教程——CUDA Driver API tensorRT从零起步迈向高性能工业级部署&#xff08;就业导向&#xff09; 课程笔记&#xff0c;讲师讲的不错&#xff0c;可以去看原视频支持下。 Driver API概述 CUDA 的多级 API CUDA 的 API 有多级&#xff08;下图&#xff09;&#xff…

CUDA编程入门极简教程

CUDA编程入门极简教程 转自&#xff1a;CUDA编程入门极简教程 作者&#xff1a;小小将 前言 2006年&#xff0c;NVIDIA公司发布了CUDA&#xff0c;CUDA是建立在NVIDIA的CPUs上的一个通用并行计算平台和编程模型&#xff0c;基于CUDA编程可以利用GPUs的并行计算引擎来更加高效地…

精简CUDA教程——CUDA Runtime API

精简CUDA教程——CUDA Runtime API tensorRT从零起步迈向高性能工业级部署&#xff08;就业导向&#xff09; 课程笔记&#xff0c;讲师讲的不错&#xff0c;可以去看原视频支持下。 Runtime API 概述 环境 图中可以看到&#xff0c;Runtime API 是基于 Driver API 之上开发的…