一文学会CUDA编程:深入了解CUDA编程与架构(一)

news2024/11/15 9:54:43

前言:

CUDA(Compute Unified Device Architecture,统一计算设备架构)是由NVIDIA公司开发的一种并行计算平台和编程模型。CUDA于2006年发布,旨在通过图形处理器(GPU)解决复杂的计算问题。在早期,GPU主要用于图像处理和游戏渲染,但随着技术的发展,其并行计算能力被广泛应用于科学计算、工程仿真、深度学习等领域。

CUDA的工作原理

CUDA的核心思想是将计算任务分配给GPU上的大量线程,这些线程可以并行地执行任务,从而实现高性能计算。CUDA将GPU划分为多个独立的计算单元,称为“流处理器”(Streaming Processor),这些流处理器可以独立地执行指令,互相加不干扰。

硬件层面

1、CUDA核心 (CUDA Core)

CUDA核心是执行线程计算的基本硬件单元。每个CUDA核心可以执行一个线程的计算任务。

图片

2、SM (Streaming Multiprocessor)

流多处理器 (SM) 是由多个CUDA核心组成的集成单元。每个SM负责管理和执行一个或多个线程块。SM内部有共享内存和缓存,用于加速数据访问和计算。

3、设备 (Device)

设备指的是整个GPU硬件。一个设备包含多个SM,能够处理大量并行计算任务。设备通过高带宽的内存和数据传输机制与主机(如CPU)进行数据交换。

图片

软件层面

1、线程 (Thread)

在CUDA编程中,线程是执行基本计算任务的最小单位。每个线程执行相同的程序代码,但可以处理不同的数据。

图片

2、线程块 (Thread Block)

线程块是由多个线程组成的集合。线程块中的线程可以共享数据,并且可以通过同步机制来协调彼此的工作。线程块的大小在程序执行时是固定的。

图片

3、网格 (Grid)

网格是由多个线程块组成的更大集合。网格中的所有线程块并行执行任务,网格的大小也在程序执行时固定。

图片

示例

实现两个向量相加 arr_c[] = arr_a[] +arr_b[]

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

#include <cmath>
#include <iostream>

#define CUDA_CHECK(call)                                           \
    {                                                              \
        const cudaError_t error = call;                            \
        if (error != cudaSuccess) {                                \
            fprintf(stderr, "Error: %s:%d, ", __FILE__, __LINE__); \
            fprintf(stderr, "code: %d, reason: %s\n", error,       \
                    cudaGetErrorString(error));                    \
            exit(1);                                               \
        }                                                          \
    }

__global__ void addKernel(float *pA, float *pB, float *pC, int size)
{
    int index = blockIdx.x * blockDim.x + threadIdx.x; // 计算当前数组中的索引
    if (index >= size)
        return;

    pC[index] = pA[index] + pB[index];
}

int main()
{
    float a[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
    float b[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};

    int arr_len = 16;

    float *dev_a, *dev_b, *dev_c;
    CUDA_CHECK(cudaMalloc(&dev_a, sizeof(float) * arr_len));
    CUDA_CHECK(cudaMalloc(&dev_b, sizeof(float) * arr_len));
    CUDA_CHECK(cudaMalloc(&dev_c, sizeof(float) * arr_len));

    CUDA_CHECK(cudaMemcpy(dev_a, a, sizeof(float) * arr_len, cudaMemcpyHostToDevice));
    CUDA_CHECK(cudaMemcpy(dev_b, b, sizeof(float) * arr_len, cudaMemcpyHostToDevice));

    int *count;
    CUDA_CHECK(cudaMalloc(&count, sizeof(int)));
    CUDA_CHECK(cudaMemset(count, 0, sizeof(int)));

    addKernel<<<arr_len + 512 - 1, 512>>>(dev_a, dev_b, dev_c, arr_len);

    float *output = (float *)malloc(arr_len * sizeof(float));

    CUDA_CHECK(cudaMemcpy(output, dev_c, sizeof(float) * arr_len, cudaMemcpyDeviceToHost));

    std::cout << " output add" << std::endl;
    for (int i = 0; i < arr_len; i++) {
        std::cout << " " << output[i];
    }
    std::cout << std::endl;

    return 0;
}

代码理解

addKernel<<<arr_len + 512 - 1, 512>>>

函数类型如下

addKernel<<<dim3 grid, dim3 block>>>

前面的表达等价于

addKernel<<<(dim3 grid(arr_len + 512 - 1), 1, 1), dim3 block(512, 1, 1)>>>

grid 与block 理解

假设只使用16个元素, arr_len =16

1、使用调整block的参数:

1.1只有x:

dim3 grid(1, 1, 1), block(arr_len, 1, 1); // 一个block里面有16个线程                   // 设置参数

图片

此时遍历的代码如下:

__global__ void addKernel(float *pA, float *pB, float *pC, int size){// block是一维的    int index = threadIdx.x; // 计算当前数组中的索引    if (index >= size)        return;    pC[index] = pA[index] + pB[index];}

1.2 含有x, y

dim3 grid(1, 1, 1), block(8, 2, 1); //每个block x方向有8个线程,总共2组。 

图片

__global__ void addKernel(float *pA, float *pB, float *pC, int size){  // block是二维的    int index = threadIdx.x + blockDim.x* threadIdx.y; // 计算当前数组中的索引    if (index >= size)        return;    pC[index] = pA[index] + pB[index];}

2、更改grid 参数

2.1 只更改x方向的参数

dim3 grid(16, 1, 1), block(1, 1, 1);   //还有16个block, 每个block就一个线程                 // 设置参数

图片

__global__ void addKernel(float *pA, float *pB, float *pC, int size){  // grid.x是一维的    int index = blockIdx.x; // 计算当前数组中的索引    if (index >= size)        return;    pC[index] = pA[index] + pB[index];}

3、grid, block参数都改

3.1 grid block各改一个

dim3 grid(4, 1, 1), block(4, 1, 1) // 代码还有4个x方向block, 每个block x方向有4个线程

图片

__global__ void addKernel(float *pA, float *pB, float *pC, int size){  // grid.x是一维的    int index = blockIdx.x*gridDim.x + threadIdx.x; // 计算当前数组中的索引    if (index >= size)        return;    pC[index] = pA[index] + pB[index];}

3.2 grid block更改两个

dim3 grid(2, 2, 1), block(2, 2, 1) // 代码还有2个X方向block,Y方向上有两组, 每个block x方向有2个线程, y方向上有两组

图片

__global__ void addKernel(float *pA, float *pB, float *pC, int size){      // 在第几个块中 * 块的大小 + 块中的x, y维度(几行几列)    int index = (blockIdx.y * gridDim.x + blockIdx.x) * (blockDim.x * blockDim.y) + threadIdx.y * blockDim.y + threadIdx.x;    if (index >= size)        return;    pC[index] = pA[index] + pB[index];}

总结

CUDA作为一种强大的并行计算平台和编程模型,极大地推动了高性能计算、深度学习等领域的快速发展。通过掌握CUDA,开发者可以充分利用GPU的并行计算能力,显著提升程序的运行效率和性能。无论是科学研究还是商业应用,CUDA都提供了广阔的可能性和机遇。

关注我的公众号auto_driver_ai(Ai fighting), 第一时间获取更新内容。

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

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

相关文章

x264 环路滤波原理系列:x264_macroblock_deblock_strength 函数

x264_macroblock_deblock_strength 函数 功能:计算去块滤波强度值,去块强度值决定了去块滤波器对像素值调整的程度。这些值通常基于以下因素:量化参数(QP):较高的QP值可能导致更强烈的去块;宏块的纹理复杂度:具有更复杂纹理的宏块可能需要更细致的去块处理;宏块的类型…

选项卡切换组件容器的实例

实现效果 点击选项卡A、B、C、D、E分别控制组件容器内各个形状组件的显隐。 实现流程 首先需要选择组件容器内的形状组件&#xff0c;默认实例是3个&#xff0c;如需添加多个可在数据中继续添加。 添加【选项卡】组件&#xff0c;在样式中设置5列&#xff0c;数据添加一列&am…

Jupyter Notebook无法自动打开浏览器解决方案

Step1&#xff1a; 在C盘&#xff08;默认C盘&#xff09;&#xff0c;找到用户文件夹 Step2&#xff1a; 打开用户文件夹&#xff0c;找到自己的“电脑名”文件夹 Step3&#xff1a; 打开“电脑名”文件夹&#xff0c;找到“.jupyter”文件夹 Step4&#xff1a; 打开“.ju…

猫头虎分享:9个实用的GPT-4o提示词

&#x1f389; 猫头虎分享&#xff1a;9个实用的GPT-4o提示词 摘要 在这篇文章中&#xff0c;猫头虎将与大家分享9个非常实用的GPT-4o提示词。这些提示词涵盖了从草图到App代码生成、通用网络爬虫到求职助理等多个领域。我们将深入探讨如何利用这些提示词提升工作效率和创作能…

【前端 · 面试 】HTTP 总结(十)—— HTTP 缓存应用

最近我在做前端面试题总结系列&#xff0c;感兴趣的朋友可以添加关注&#xff0c;欢迎指正、交流。 争取每个知识点能够多总结一些&#xff0c;至少要做到在面试时&#xff0c;针对每个知识点都可以侃起来&#xff0c;不至于哑火。 前端面试http总结.012 前言 通过前面几篇内容…

2024宁波工业装备博览会-相聚12月

2024宁波工业装备博览会-相聚12月 时间&#xff1a;2024年12月2-4日 地点&#xff1a;宁波国际会展中心 2024中国(宁波)工业装备博览会展出面积、展品内容在不断扩大&#xff0c;专业观众成倍增加&#xff0c;极大地推动宁波智能制造产业的国际交流及贸易市场的发展。展会不…

企业如何通过有效的库存管理来降低库存成本?

企业如何通过有效的库存管理来降低库存成本&#xff1f; 那么如何在满足市场需求的同时&#xff0c;最大限度地减少资金占用、降低仓储成本、避免库存积压与损耗呢&#xff1f; 这个问题很好回答&#xff0c;本文我想带你了解WMS仓库管理系统&#xff0c;其能够有效并精准的帮…

选择最佳SOLIDWORKS服务商:您的成功之钥

在当今快速发展的制造业环境中&#xff0c;选择合适的SOLIDWORKS服务商对于确保您的项目成功至关重要。无论是初次接触SOLIDWORKS还是希望提升现有的设计流程&#xff0c;找到一位可靠的服务商都能为您提供所需的技术支持和服务。本文将帮助您了解如何选择最佳的SOLIDWORKS服务…

推荐3款电脑上不可或缺的神仙软件

Allen Explorer Allen Explorer是一款功能强大的文件管理软件&#xff0c;旨在替代Windows系统的“我的电脑”。它采用了类似Chrome的界面设计&#xff0c;简洁美观&#xff0c;支持多标签页、双窗口、收藏夹等功能&#xff0c;极大地优化了文件操作体验。用户可以对文件项目进…

使用 JavaScript 对图像进行量化并提取主要颜色

前言 前段时间在 Halo 的 应用市场 中遇到希望主题和插件的封面图背景色为封面图主色的问题&#xff0c;于是乎需要根据封面图提取主色就想到使用 K-Means 算法来提取。 在图像处理中&#xff0c;图像是由像素点构成的&#xff0c;每个像素点都有一个颜色值&#xff0c;颜色值…

Gstreamer结合腾讯云进行rtmp直播

直播效果&#xff1a; 一、注册腾讯云直播账户&#xff0c;生成rtmp推流地址 腾讯云直播地址&#xff1a; https://console.cloud.tencent.com/live 首先需要注册登录。然后电机生成直播地址&#xff1a; 输入自己的流名字&#xff0c;比如test 复制这个RTMP地址。 这时候&am…

【数据结构与算法】循环队列

循环队列 一.循环队列的引入二.循环队列的原理三.循环队列判断是否为满或空1.是否为空2.是否为满 四.循环队列入队五.循环队列出队六.循环队列的遍历七.循环队列获取长度八.总结 一.循环队列的引入 还记得我们顺序队列的删除元素嘛,我们有两种方式,一种是将数组要删除元素后面…

系统数据库

Mysql数据库安装完成后&#xff0c;自带了一下四个数据库&#xff0c;具体作用如下&#xff1a; 常用工具&#xff1a;

<数据集>工程机械识别数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;6338张 标注数量(xml文件个数)&#xff1a;6338 标注数量(txt文件个数)&#xff1a;6338 标注类别数&#xff1a;7 标注类别名称&#xff1a;[Excavator, Loader, Dumb_truck, Mobile_crane, Roller, Bull_dozer, …

功能实现——采用 Hutool 工具发送邮件

目录 1.需求分析2.准备工作&#xff1a;开通邮箱的 SMTP 服务3.项目环境搭建4.代码实现mail.htmlEmployee.javaMailController.javaMailService.javaMailServiceImpl.java 5.测试 1.需求分析 采用 Hutool 工具来实现发送邮件的功能&#xff0c;具体来说&#xff1a;为新员工发…

准备笔试第21天,牛客.十字爆破牛客.比木名居的桃子牛客.chinka蜜柑01背包

目录 牛客.十字爆破 牛客.比木名居的桃子 牛客.chinka蜜柑 01背包 牛客.十字爆破 就是上下左右加上&#xff0c;但是会遇到的问题就是&#xff0c;这块并不容易去获取得分&#xff0c;如果可能要四重循环&#xff0c;遍历这一行&#xff0c;这一列&#xff0c;然后把他们存在…

解决Ubuntu报错:sudo: /etc/sudoers is world writable

1. 情况描述 /etc/sudoer这个文件的权限由440变成了777&#xff0c;由于账户下有多个子账户&#xff0c;导致子账户的sudo权限不能使用。报错如下&#xff1a; 2.解决办法 执行下面的语句就ok了 pkexec chmod 0440 /etc/sudoers 参考链接 3.总结 不要随便改系统文件的权…

模型组合、注意力机制在单步、多步、单变量、多变量预测中的应用

往期精彩内容&#xff1a; 时序预测&#xff1a;LSTM、ARIMA、Holt-Winters、SARIMA模型的分析与比较-CSDN博客 VMD CEEMDAN 二次分解&#xff0c;Transformer-BiGRU预测模型-CSDN博客 独家原创 | 基于TCN-SENet BiGRU-GlobalAttention并行预测模型-CSDN博客 独家原创 | B…

a newer version of WinPcap,ensp安装时候winpcap软件报错

ensp安装时候winpcap软件报错 a newer version of WinPcap… 找到C盘路径下的文件Packet.dll C:\Windows\SysWOW64 修改为&#xff1a;Packet.dll.1&#xff08;后缀名随便改一下&#xff09; 再次安装&#xff0c;成功

在线PS快速抠出透明背景(纯色背景+复杂背景抠图操作)

电脑硬盘快爆了&#xff0c;没必要安装个PS了&#xff0c;网上找了几个在线的PS网站&#xff0c;还别说&#xff0c;一般的PS操作都可以满足 我们使用PS通常用的较多的是抠背景操作吧&#xff0c;接下来演示几个在在线PS网站上进行抠背景操作 一、在线PS网站 Photopea&#x…