【CUDA1】GPUvsCPU,CUDA Kernel

这个系列我们来讲解CUDA,从入门到可以独立写自己的cuda代码,现在开启我们的cuda之旅吧。

CPU:少量非常强的核心,一个核心很强,擅长:

  • 复杂逻辑
  • 分支判断
  • 操作系统
  • Python 程序
  • 各种串行任务

GPU:大量相对简单的计算单元,同时执行大量相似任务。

CPU有内存,RAM,GPU有显存,VRAM。

复制代码
x = torch.randn(1000, 1000)//默认是CPU RAM
print(x.device)//CPU

x = torch.randn(1000, 1000, device="cuda")//GPU VRAM
print(x.device)//cuda:0 第 0 张 NVIDIA GPU

y = torch.randn(1000, 1000, device="cuda")

z = x @ y//矩阵乘法

第一个程序(建议手写)

python 复制代码
import torch  
  
print("CPU:")  
x = torch.randn(3,3)  
print(x)  
print("device:",x.device)  
  
  
print()  
  
print("GPU:")  
y = torch.randn(3,3,device="cuda")  
print(y)  
print("device:",y.device)

什么是CUDA kernel?

可以把它理解为让 GPU 执行的一段程序,比如我们需要Ci = Ai + Bi;有1亿个元素,GPU启动大量线程

复制代码
Thread 0 → C[0] = A[0] + B[0]

Thread 1 → C[1] = A[1] + B[1]

Thread 2 → C[2] = A[2] + B[2]

Thread 3 → C[3] = A[3] + B[3]

...

Thread 99999999 → C[99999999] = ...

当然GPU不是真的同时拥有这么多的物理计算核心,所以我们需要把thread分组,若干个thread合成一个block,我们再将所有的block集合为grid,于是形成了一个层级结构

复制代码
                 Grid
                  │
       ┌──────────┼──────────┐
       ↓          ↓          ↓
    Block 0    Block 1    Block 2
       │          │          │
    Threads    Threads    Threads

GPU内部存在一种叫SM的计算单位,暂时可以理解为GPU里面真正负责执行CUDA Thread的计算单元。我们现在不讨论这个,就直接进入threads步骤,每个thread都有自己的ID,CUDA给我们提供threadIdx来获取thread的编号

eg:int i = threadIdx.x;//c++

Ci = Ai + Bi;//thread就知道自己负责谁了

这个i其实不会太大,因为block的存在,如果大了的话,我们会换一个block,同样的,CUDA提供blockIdx表示我是第几个block,再加上threadIdx,表示我是这个block的第几个thread,于是全局的Thread ID可以计算

c++ 复制代码
int i = blockIdx.x*blockDim.x+threadIdx.x;

我们来算一下,block0 thread0是多少?

假设每个block有256个thread

int i = 0 * 256+0=0;这个就是CUDA把大数组分给GPU的核心方法。

CUDA程序实际上是在协调CPU和GPU。

复制代码
             CPU
              │
              │ 启动 Kernel
              ↓
             GPU
              │
              ↓
          CUDA Kernel
              │
       ┌──────┼──────┐
       ↓      ↓      ↓
     Thread Thread Thread

first CUDA

我们之前写的import torch,它使用torch库来直接调用CUDA Kernel,现在我们开始接触真正的CUDA C++。

复制代码
__global__ void add(float* A, float* B, float* C)
{
    int i = blockIdx.x * blockDim.x + threadIdx.x;

    C[i] = A[i] + B[i];
}
相关推荐
鶴哥只手遮天7 小时前
深入 opencode(上篇):工程全景、双会话内核与事件溯源
人工智能
成为深度学习高手8 小时前
TimeBridge:用Integrated Attention与Cointegrated Attention分别桥接短期平稳与长期协整的时序预测模型
人工智能·机器学习·数据挖掘
知几蜗牛8 小时前
Java 17调用Embeddings API:余弦相似度与FAQ拒答阈值
人工智能
知几蜗牛8 小时前
Python消费Responses SSE事件:增量文本、超时与取消
人工智能
AI日报派送佬8 小时前
2026年10月4日AI行业日报|AI智能体自主能力升级,模型落地与安全规范双向迭代
人工智能·智能体·ai安全·开源ai·ai日报·人工智能前沿·ai科研
蒲公英eric8 小时前
人口增长问题:从 Malthus 到 Logistic 的建模之旅
人工智能·python·数学建模·人口增长问题
知几蜗牛8 小时前
Python调用Audio Speech REST API:文本分段、超时与原子落盘
人工智能
打工仔折腾 AI8 小时前
把 AI Agent 托管到家里电脑:UU远程端口映射与CLI实测记录
人工智能·后端·python·langchain·电脑·ai agent 实战
枯木◊靠推文躺平版8 小时前
AI音乐成品优化工具怎么选:从 demo 听感到可发布状态
人工智能
YH55269848 小时前
怎么看 OpenAI 的 Pro 订阅取消 5x 和 20x 的描述?
人工智能·chatgpt