← 开源
gau-nernst

learn-cuda

Learn CUDA with PyTorch

TutorialsTool-specific tutorialsCuda
在 GitHub 打开
增长势头
+024 小时新增 Star0.0%
505
Star
67
Fork
2
贡献者
创建于 2024-02-04 · 更新于 2026-10-15 · 今日第 18207 名
主要开发者
gau-nernstbenenzhu

gau-nernst/learn-cuda 排名第 18,207,有 505 个星标。

同类别比较

gau-nernst/learn-cuda 排名第 18,207,此处有 8 个同类条目;SmartFlowAI/Llama3-Tutorial 排名第 18,226。

同类别比较
名称排名指标
rasbt/stat479-machine-learning-fs1818,161
语言:
Jupyter Notebook
星标数:
507
分叉数:
230
简介:
Course material for STAT 479: Machine Learning (FS 2018) at University Wisconsin-Madison
cloudxlab/ml18,180
语言:
Jupyter Notebook
星标数:
506
分叉数:
479
简介:
Machine Learning Projects and Learning Content
davidefiocco/streamlit-fastapi-model-serving18,181
语言:
Python
星标数:
506
分叉数:
92
简介:
Simple web app example serving a PyTorch model using streamlit and FastAPI
huggingface/large_language_model_training_playbook18,185
语言:
Python
星标数:
506
分叉数:
23
简介:
An open collection of implementation tips, tricks and resources for training large language models
SmartFlowAI/Llama3-Tutorial18,226
语言:
Python
星标数:
504
分叉数:
53
简介:
Llama3-Tutorial(XTuner、LMDeploy、OpenCompass)
hemingkx/ChineseNMT18,236
语言:
Python
星标数:
504
分叉数:
90
简介:
ChineseNMT: Translate English to Chinese with PyTorch Implementation of Transformer
jiahe7ay/MINI_LLM18,239
语言:
Python
星标数:
504
分叉数:
73
简介:
This is a repository used by individuals to experiment and reproduce the pre-training process of LLM.
shayneobrien/generative-models18,244
语言:
Jupyter Notebook
星标数:
504
分叉数:
72
简介:
Annotated, understandable, and visually interpretable PyTorch implementations of: VAE, BIRVAE, NSGAN, MMGAN, WGAN, WGANGP, LSGAN, DRAGAN, BEGAN, RaGAN, InfoGAN, fGAN, FisherGAN
关键参数与规格
关键参数与规格
参数值
语言Cuda
类别Tutorials
子类别Tool-specific tutorials
关键词CUDA programming, Kernel, Memory management, Optimization
星标数505
分叉数67
贡献者2
创建日期2024-02-04
更新日期2026-10-15
1 天星标数0
排名18,207
上次排名7,079
排名变化-11,128
7 天星标排名19,351
上次 7 天星标排名19,332
7 天星标排名变化-19
总星标排名19,213
上次总星标排名19,185
总星标排名变化-28
国家Singapore
README 摘录

Vector addition | Simple example to get everything working. Matrix multiplication SIMT | Block tiling, thread tiling, warp tiling. Matrix multiplication SM80 | Inline PTX, , , . Matrix multiplication SM100 | tcgen05 02\. FP6 | FP6 primitives (FP32/FP16/BF16 FP6). Row-scaled matmul | Simple epilogue and open the generated file in Nsight Compute. See more here: To profile PyTorch program, run and open the saved file at See more here: To support syntax highlighting and code suggestion in IDE, add the following include paths (can be

seen in the command that PyTorch uses to compile inline C++ code). Change the paths appropriately for your system. For Windows, the paths are slightly different, but then again, you can see them in the PyTorch compile command. For VSCode, add the paths to (VSCode will prompt you to create one if it does not exist). Learnings CUDA architecture: a GPU consists of multiple **Streaming Multiprocessors** (SMs). All threads in a warp share a program counter. In other words, all

threads in a warp must execute the same instruction (Single Instruction, Multiple Threads - SIMT). If threads in a warp have to execute different instructions (e. due to branching), there will be **warp divergence**: each instruction will be executed sequentially. Note that threads in different warps executing different instructions is fine (e. threads 0-31 do A, threads 32-63 do B -> no warp divergence). Block (of threads) is a software-defined concept. It consists of a user-defined number of

threads (max 1024 for most consumer GPUs). It will be executed by a single SM - the threadblock is partitioned into warps, and each warp is scheduled to execute. There are 3 main types of memory (in order of increasing speed and decreasing capacity): **Global memory** (DRAM or HBM): this consists of off-chip memory modules. This is typically in order of GBs (8-16GB for consumer GPUs). In user code, you allocate globaly memory with and write data to it

with . **L2 cache** **Shared memory + L1 cache** (SRAM): this is on-chip memory. Traditionally NVIDIA GPUs only have 48kb shared memory per SM, but later generations can have up to 100kb. This is private for each SM, hence it is shared within a threadblock. Usually local variables are backed by registers, as determined by the compiler. Performant memory access: ( Typically, we load a tile of data (might be larger than block size) from global memory to shared memory, do computations

on shared memory, then write results from shared memory back to global memory. To achieve coalesced memory access (and making the kernel easier to reason about), usually we decouple global memory access from computation: during global memory access, we assign consecutive threads to consecutive data, but during computation, a thread may be responsible for a different data element. When writing Triton kernel, always use . With fp32 inputs, the outputs are wrong. With fp16/bf16, this flag doesn't matter.

常见问题

记录了多少星标和分叉?

gau-nernst/learn-cuda 有 505 个星标和 67 个分叉。

仓库排名是多少?

gau-nernst/learn-cuda 排名第 18,207。

记录的语言和类别是什么?

gau-nernst/learn-cuda 有 505 个星标,语言为 Cuda,类别为 Tutorials。

哪个仓库排名最接近?

gau-nernst/learn-cuda 与 SmartFlowAI/Llama3-Tutorial 比较,后者排名第 18,226,有 504 个星标。

README

Learn CUDA with PyTorch

Resources:

Name Description
01. Vector addition Simple example to get everything working.
02. Matrix multiplication SIMT Block tiling, thread tiling, warp tiling.
02. Matrix multiplication SM80 Inline PTX, cvta, ldmatrix, mma.
02. Matrix multiplication SM100 tcgen05
02. Matrix multiplication SM120
02. Matrix multiplication CDNA3
03. Sum Reduction in general. Prepare for softmax (max and sum).
04. Softmax Naive (safe) softmax, online softmax. atomicCAS(). Single-block and multi-block per row.
05. FP6 FP6 primitives (FP32/FP16/BF16<->FP6).
06. Box blur 2D CUDA blocks/threads. TODO: optimize with separable filters, moving average.
07. Attention Flash attention
08. Row-scaled matmul Simple epilogue
# profile a CUDA kernel
# remember to compile with -lineinfo
ncu --set full --import-source on -o profile python main.py

# debug illegal memory access
compute-sanitizer python main.py

and open the generated profile.ncu-rep file in Nsight Compute. See more here: https://docs.nvidia.com/nsight-compute/NsightComputeCli/index.html

To profile PyTorch program, run

with torch.profiler.profile() as prof:
    # PyTorch program here
    ...

print(prof.key_averages().table(sort_by="cuda_time_total", row_limit=10))
prof.export_chrome_trace("trace.json")

and open the saved trace.json file at https://ui.perfetto.dev/. See more here: https://pytorch.org/docs/stable/profiler.html#torch.profiler.profile

To support syntax highlighting and code suggestion in IDE, add the following include paths (can be seen in the command that PyTorch uses to compile inline C++ code).

"/home/thien/miniconda3/envs/dev/lib/python3.10/site-packages/torch/include",
"/home/thien/miniconda3/envs/dev/lib/python3.10/site-packages/torch/include/torch/csrc/api/include",
"/home/thien/miniconda3/envs/dev/lib/python3.10/site-packages/torch/include/THC",
"/usr/local/cuda/include",
"/home/thien/miniconda3/envs/dev/include/python3.10"

Change the paths appropriately for your system. For Windows, the paths are slightly different, but then again, you can see them in the PyTorch compile command. For VSCode, add the paths to .vscode/c_cpp_properties.json (VSCode will prompt you to create one if it does not exist).

Learnings

  • CUDA architecture: a GPU consists of multiple Streaming Multiprocessors (SMs). Each SM executes multiple warps. Each warp contains 32 CUDA threads.
  • All threads in a warp share a program counter. In other words, all threads in a warp must execute the same instruction (Single Instruction, Multiple Threads - SIMT). If threads in a warp have to execute different instructions (e.g. due to branching), there will be warp divergence: each instruction will be executed sequentially. Note that threads in different warps executing different instructions is fine (e.g. threads 0-31 do A, threads 32-63 do B -> no warp divergence).
  • Block (of threads) is a software-defined concept. It consists of a user-defined number of threads (max 1024 for most consumer GPUs). It will be executed by a single SM - the threadblock is partitioned into warps, and each warp is scheduled to execute.
  • There are 3 main types of memory (in order of increasing speed and decreasing capacity):
    • Global memory (DRAM or HBM): this consists of off-chip memory modules. Your normal data (tensors, ...) reside here. This is typically in order of GBs (8-16GB for consumer GPUs). In user code, you allocate globaly memory with cudaMalloc() and write data to it with cudaMemcpy().
    • L2 cache
    • Shared memory + L1 cache (SRAM): this is on-chip memory. Traditionally NVIDIA GPUs only have 48kb shared memory per SM, but later generations can have up to 100kb. This is private for each SM, hence it is shared within a threadblock.
      • Unused shared memory is allocated to L1 cache.
      • This can be used as working space for storing intermediate results and collaboration among threads within a block.
      • To use it in kernel code, we either write __shared__ float shmem[64]; for static-size array, or extern __shared__ float shmem[]; for dynamically allocated shared memory, which is set by kernel call execution configuration kernel<<>>().
      • To use more than 48kb of shared memory, we need to use cudaSetFuncAttribute().
    • Register file: per-thread memory. Usually local variables are backed by registers, as determined by the compiler. All registers are 32-bit.
  • Performant memory access: (https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#device-memory-accesses)
    • Global memory: to ensure coalesced memory access (i.e. threads in a warp accessing different memory locations with a single instruction), the rule of thumb is to make consecutive threads accessing consecutive memory locations (+ memory alignment requirement, which is most of the time satisfied). (L1 and L2. Cache line...) A global memory transaction has a maximum of 128 bytes (e.g. 32 fp32 or 32 int32). Rule of thumb - each thread loads 16 bytes (128 bits) (equivalent to float4). For direct global->shared memory copy without using registers, we can use cp.async.
    • Shared memory: to avoid memory bank conflict...
  • Typically, we load a tile of data (might be larger than block size) from global memory to shared memory, do computations on shared memory, then write results from shared memory back to global memory. To achieve coalesced memory access (and making the kernel easier to reason about), usually we decouple global memory access from computation: during global memory access, we assign consecutive threads to consecutive data, but during computation, a thread may be responsible for a different data element.
  • When writing Triton kernel, always use tl.dot(allow_tf32=False). With fp32 inputs, the outputs are wrong. There are no clear reasons for this. With fp16/bf16, this flag doesn't matter.
排名相邻
同类项目