CUDA线程的线程层次结构,以及单个线程threadIdx如何使用stride来进行跳步操作,同时对多个数据进行计算

news2024/10/7 20:25:29

线程层次的概念:

简单说,就是一个grid有多个block,一个block有多个thread.

grid有多大,用gridDim表示它有多少个block,具体分为gridDim.x, gridDim.y,gridDim.z。

block有多大,用blockDim表示它有多少个thread,具体分为blockDim.x,blockDim.y,blockDim.z。

怎么表示thread在block中的相对位置呢?用 threadIdx.x,threadIdx.y,threadIdx.z表示。

怎么表示block在grid中的相对位置呢?用blockIdx.x,blockIdx.y,blockIdx.z表示。

顺便解释下 华为云论坛_云计算论坛_开发者论坛_技术论坛-华为云 中hello_from_gpu<<<x,y>>>(); 中的x和y是什么意思?它们分别表示 gridDim和blockDim。

 

对于下面这个函数:

表示gridDim是1,表示grid有1个block,blockDim是4。表示block有4个thread。

所以对于上面的核函数,相当于有4个thread分别执行了 c[n]=a[n]+b[n]的操作,n=threadIdx.x

在调用的时候,所有的CUDA核都是执行同一个函数。这与CPU多线程可能会执行不同的任务不同。
 

如上图所示,Thread在CUDA core中执行,Block在 SM中执行,Grid在Device中执行。

那么,CUDA是如何执行的呢?看下面这张图:

如果没有block的概念,要同时进行同步、通信、协作时,整体的核心都要产生等待的行为,如要进行扩展时,扩展的越多等待也越多。所以性能会受影响。

但是有block的概念后,可以实现可扩展性。用block或warp就可以很容易实现扩展了。

如何找到线程该处理的数据在哪里呢?这就要提到线程索引的概念。 

以上:假定每8个thread时一个block。

具体的公式如下:

具体的索引位置 index = blockDim.x * blockIdx.x + threadIdx.x

那么一个CUDA程序到底应该怎么写呢?

以将一个CPU实现的代码转换为GPU为例: 

CPU的实现过程大致如下:

(1)主程序main:

先分配 源地址空间a,b,目的地址空间c,并生成a,b的随机数。然后调用 一维矩阵加的CPU函数。

(2)一维矩阵加的CPU函数:

遍历a,b地址空间,分别将 a[i] 与 b[i]相加,写入 c[i]地址。

这个时候,请注意是要显式地进行for循环遍历。
 

那么,GPU该如何实现呢?

(1)主程序main:

因为GPU存在Host和Device内存,所以先申请host内存h_a,h_b,存放a,b的一维矩阵的内容(也可以生成随机数),并申请host内存h_c存放c的计算结果。

然后申请device内存,这个时候,需要申请 d_a,d_b两个源device内存(cudaMalloc),以及d_c这个目的device内存(cudaMalloc)。将h_a和h_b的内容拷贝到d_a和d_b (显然需要使用 cudaMemcpyHostToDevice);

然后调用核函数完成GPU的并行计算,结果写入h_c;

最后将d_c的device内存写回到h_c(cudaMemcpyDeviceToHost),并释放所有的host内存(使用free)和device内存(使用cudaFree)。

(2)核函数

这里就是重点了。核函数只需要去掉最外层的循环,并且根据前面 的index写法,将i替换成index的写法即可。

如何设置Gridsize和blocksize呢?

对于一维的情况:

block_size=128;

grid_size = (N+ block_size-1)/block_size;

(没有设成什么值是最好的)

每个block可以申请多少个线程呢?

总数也是1024。如(1024,1,1)或者(512,2,1)

grid大小没有限制。

底层是以warp为单位申请。 如果blockDim为160,则正好申请5个warp。如果blockDim为161,则不得不申请6个warp。

如果数据过大,线程不够用怎么办?

这样子,每个线程需要处理多个数据。

 

比如对于上图,线程0,需要处理 0,8,16,24 四个数据。核函数需要将每一个大块都跑一遍。代码如下:

这里引入了一个stride的概念,它的大小为blockDim.x X gridDim.x 。核函数需要完成每个满足 index = index + stride * count对应的相关地址的计算。

范例1:体验index

Index_of_thread.cu

#include <stdio.h>
 
__global__ void hello_from_gpu()
{
   //仅仅是在原先代码的基础上打印 blockIdx.x 和 threadIdx.x
    const int bid = blockIdx.x;
    const int tid = threadIdx.x;
    printf("Hello World from block %d and thread %d!\n", bid, tid);
}
 
int main(void)
{
    hello_from_gpu<<<5, 5>>>();
    
    //记得加上同步,不然结果会出不来。
    cudaDeviceSynchronize();
    return 0;
}

Makefile:

TEST_SOURCE = Index_of_thread.cu
 
TARGETBIN := ./Index_of_thread
 
CC = /usr/local/cuda/bin/nvcc
 
$(TARGETBIN):$(TEST_SOURCE)
	$(CC)  $(TEST_SOURCE) -o $(TARGETBIN)
 
.PHONY:clean
clean:
	-rm -rf $(TARGETBIN)

编译并执行:

范例2:完成一维向量计算:add

vectorAdd.cu

#include <math.h>
#include <stdio.h>
 
void __global__ add(const double *x, const double *y, double *z, int count)
{
    const int n = blockDim.x * blockIdx.x + threadIdx.x;
    
    //这里判断是防止溢出
	if( n < count)
	{
	    z[n] = x[n] + y[n];
	}
 
}
void check(const double *z, const int N)
{
    bool error = false;
    for (int n = 0; n < N; ++n)
    {
        //检查两个值是否相等,如不等则error=true.
        if (fabs(z[n] - 3) > (1.0e-10))
        {
            error = true;
        }
    }
    printf("%s\n", error ? "Errors" : "Pass");
}
 
 
int main(void)
{
    const int N = 1000;
    const int M = sizeof(double) * N;
    
    //分配host内存
    double *h_x = (double*) malloc(M);
    double *h_y = (double*) malloc(M);
    double *h_z = (double*) malloc(M);
 
    //初始化一维向量的值
    for (int n = 0; n < N; ++n)
    {
        h_x[n] = 1;
        h_y[n] = 2;
    }
 
    double *d_x, *d_y, *d_z;
 
    //分配device内存
    cudaMalloc((void **)&d_x, M);
    cudaMalloc((void **)&d_y, M);
    cudaMalloc((void **)&d_z, M);
    
    //host->device
    cudaMemcpy(d_x, h_x, M, cudaMemcpyHostToDevice);
    cudaMemcpy(d_y, h_y, M, cudaMemcpyHostToDevice);
 
    //这个是公式。记住就可以了。
    const int block_size = 128;
    const int grid_size = (N + block_size - 1) / block_size;
    
    //核函数计算
    add<<<grid_size, block_size>>>(d_x, d_y, d_z, N);
 
    //device->host
    cudaMemcpy(h_z, d_z, M, cudaMemcpyDeviceToHost);
    
    //检查结果
    check(h_z, N);
 
    //释放host内存
    free(h_x);
    free(h_y);
    free(h_z);
    
    //释放device内存
    cudaFree(d_x);
    cudaFree(d_y);
    cudaFree(d_z);
    return 0;
}

Makefile-add
TEST_SOURCE = vectorAdd.cu
 
TARGETBIN := ./vectorAdd
 
CC = /usr/local/cuda/bin/nvcc
 
$(TARGETBIN):$(TEST_SOURCE)
	$(CC)  $(TEST_SOURCE) -o $(TARGETBIN)
 
.PHONY:clean
clean:
	-rm -rf $(TARGETBIN)

编译后执行:

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

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

相关文章

SpringBoot项目结合@Slf4j将日志记录到磁盘和数据库

文章目录 1、背景介绍2、存本地2.1、配置文件2.2、使用 3、存数据库3.1、配置文件改造3.2、过滤器编写3.3、表准备3.4、添加依赖3.5、测试 4、优化4.1、日志定期删除4.2、分库处理4.3、环境 5、总结 1、背景介绍 现在我一个SpringBoot项目想记录日志&#xff0c;大概可以分为下…

深度学习助力版面分析技术,图像“还原”有方

您好&#xff0c;我是码农飞哥&#xff08;wei158556&#xff09;&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f4aa;&#x1f3fb; 1. Python基础专栏&#xff0c;基础知识一网打尽&#xff0c;9.9元买不了吃亏&#xff0c;买不了上当。 Python从入门到精…

【Python 随练】分数序列

题目&#xff1a; 有一分数序列&#xff1a;2/1&#xff0c;3/2&#xff0c;5/3&#xff0c;8/5&#xff0c;13/8&#xff0c;21/13… 求出这个数列的前 20 项之和。 简介&#xff1a; 在本篇博客中&#xff0c;我们将研究一个有趣的数学问题&#xff1a;求解一个特殊数列的…

MySQL出现Specified key was too long; max key length is 3072 bytes解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

算法篇——动态规划 01背包问题 (js版)

416. 分割等和子集 给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集&#xff0c;使得两个子集的元素和相等。 链接&#xff1a;力扣 解题思路&#xff1a; 这道题看似是比较简单的背包问题&#xff1a; 首先可以通过判断数组和是否是…

MVC框架的model,view,controllr如何运作

第一步&#xff1a; MVC 是&#xff1a;model&#xff0c;view&#xff0c;controller 的缩写。 第二步&#xff1a; view负责界面显示&#xff0c;也就是jsp&#xff0c;html页面 controller是控制业务流程&#xff0c;也就是servlet&#xff0c;service等java文件 model是…

AI绘图网站 AI绘图生成器推荐

一、怎样设置关键词才能制作出美观高端的图片&#xff1f; 要在使用AI绘画软件时生成高端的优质图片&#xff0c;关键词的设置是不可或缺的重要因素。以下是一些关键词设置的建议。 确立你想要呈现的主题或题材 在设定关键字之前&#xff0c;你必须确定你所要表现的主题或题材…

基于pix实现无人机编队表演

文章目录 前言一、飞控LED灯光控制二、飞控路径控制三、飞控和地面站通信接口四、舞步设计五、gazebo仿真 前言 编队灯光表演没有什么高深的技术&#xff0c;主要是一些应用层的开发&#xff0c;事实上即使没有任何编程基础&#xff0c;按本教程操作也可以实现。 硬件准备&am…

spring security oauth2整合SSO(单点登录)

1.流程 用户在访问应用程序时&#xff0c;将被重定向到身份认证服务器进行身份验证。用户输入他们的凭据&#xff08;通常是用户名和密码&#xff09;&#xff0c;身份认证服务器对其进行验证。身份认证服务器向用户颁发一个令牌&#xff0c;该令牌表示用户已经通过身份验证。…

正则表达式(1)

文章目录 正则表达式一.基础命令1.grep命令1.1grep格式1.2grep命令选项 2.特殊的符号2.1空行——^$2.2以什么为开头—^,以什么为结尾—$2.2.1以什么为开头的格式&#xff1a;2.2.2以什么为结尾的格式&#xff1a; 3.只匹配单行——^匹配的字符$ 二.文本处理命令1.sort命令1.1命…

使用大型语言模(LLM)构建系统(七):评估1

今天我学习了DeepLearning.AI的 Building Systems with LLM 的在线课程&#xff0c;我想和大家一起分享一下该门课程的一些主要内容。之前我们已经学习了下面这些知识&#xff1a; 使用大型语言模(LLM)构建系统(一)&#xff1a;分类使用大型语言模(LLM)构建系统(二):内容审核、…

Java 10 新特性解读

前言  2018年3月21日&#xff0c;Oracle官方宣布Java10正式发布。  需要注意的是 Java 9 和 Java 10 都不是 LTS (Long-Term-Support) 版本。和过去的 Java 大版本升级不同&#xff0c;这两个只有半年左右的开发和维护期。而未 来的 Java 11&#xff0c;也就是 18.9 LTS&am…

SpringBoot基于Aop实现自定义日志注解(提供Gitee源码)

前言&#xff1a;日志在我们的日常开发当中是必定会用到的&#xff0c;在每个方法的上都会习惯性打上Log注解&#xff0c;这样系统就会自动帮我们记录日志&#xff0c;整体的代码结构就会非常优雅&#xff0c;这边我自己搭建了一个demo去实现了一些这个项目当中必定会用的功能。…

根据jar名称动态打包带版本的镜像, 并创建对应容器的脚本实现

根据jar名称动态打包带版本的镜像以及容器 利用shell脚本, 实现根据jar名称中的项目名和版本号来动态制作带版本的Docker镜像以及带版本的容器 背景 人人都逃不过的墨菲定律 事情的原因来自最近发生的一次生产环境事故: 我们在甲方那里环境中有两个服务器, 一个用于灰度测试另…

WPF开发txt阅读器16:自动编码检测

文章目录 更改编码重新载入自动编码检测更改编码并保存 txt阅读器系列&#xff1a; 需求分析和文件读写目录提取类&#x1f48e;列表控件与目录&#x1f48e;快捷键翻页字体控件绑定&#x1f48e;前景/背景颜色书籍管理系统&#x1f48e;用树形图管理书籍语音播放&#x1f48e…

Cortext-M3系统:储存器系统(2)

1、存储系统功能概览 Cortext-M3储存器有如下特点&#xff1a; 存储器映射是预定义的&#xff0c;并且还规定好了哪个位置使用哪条总线。 存储器系统支持所谓的“位带”&#xff08;bit-band&#xff09;操作。通过它&#xff0c;实现了对单一比特的原子操作&#xff0c;位带操…

STM32G0+EMW3080+阿里云实现单片机WiFi智能联网功能(一)EMW3080实现和PC之间的串口通讯

项目描述&#xff1a;该系列记录了STM32G0EMW3080实现单片机智能联网功能项目的从零开始一步步的实现过程&#xff1b; 硬件环境&#xff1a;单片机为STM32G030C8T6&#xff1b;物联网模块为EMW3080V2-P&#xff1b;网联网模块的开发板为MXKit开发套件&#xff0c;具体型号为XC…

基于tensorflow深度学习的猫狗分类识别

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

Triton教程 --- 速率限制器

Triton教程 — 速率限制器 Triton系列教程: 快速开始利用Triton部署你自己的模型Triton架构模型仓库存储代理模型设置优化动态批处理 速率限制器 速率限制器管理 Triton 在模型实例上调度请求的速率。 速率限制器在 Triton 中加载的所有模型上运行&#xff0c;以允许跨模型优…

带你用Python制作7个程序,让你感受到端午节的快乐

名字&#xff1a;阿玥的小东东 学习&#xff1a;Python、C/C 主页链接&#xff1a;阿玥的小东东的博客_CSDN博客-python&&c高级知识,过年必备,C/C知识讲解领域博主 目录 前言 程序1&#xff1a;制作粽子 程序2&#xff1a;龙舟比赛 程序3&#xff1a;艾草挂 程序4…