
Explore the differences between CPUs and GPUs, focusing on Nvidia designs and the A100 streaming multiprocessor, memory hierarchy, and how parallel cores enable independent instruction processing in GPU workloads.
Explore Nvidia's rise from the NV1 device to the GeForce generation, highlighting memory, cores, and market dominance in GPUs and gaming.
discover how to determine a gpu’s generation and architecture using examples like the A100 and RTX 3090, including the GeForce and Tesla generations and the Ampere architecture.
Understand the difference between the gpu chip and the gpu itself. The chip is the silicon heart, while the gpu adds memory, cooling, and interfaces for consumer use.
Please don't skip this video. It is pivotal for the the whole course.
Explore how compute capability versions (major.minor) classify Nvidia GPUs, shaping feature support, tensor cores, and CUDA toolkit compatibility across architectures like Volta, Ampere, and Hopper.
Explore NVIDIA GPU white papers as in-depth specifications to compare architectures. Learn to navigate the streaming multiprocessor design and track performance benchmarks and technical specs.
Install Visual Studio as editor and compiler, install CUDA toolkit 12.3 on Windows with express installation, ensure 20–21 GB free space, and update Nvidia drivers to begin CUDA programming.
Install Windows Subsystem for Linux to run Linux on Windows, choose a distribution like Ubuntu or Debian, and learn the wsl --install workflow to set up Linux for CUDA development.
Install the Nvidia CUDA toolkit on Linux via WSL, verify Nvcc, run sudo apt install Nvidia CUDA toolkit, and confirm Nvcc shows release 11.5; note potential issues and future updates.
Explore CUDA architecture and the host-device model, mapping blocks and warps to the four-level GPU hierarchy for efficient GPGPU on NVIDIA GPUs.
#include <stdio.h>
#include <cuda_runtime.h>
#include <device_launch_parameters.h>
#define SIZE 2048 // Define the size of the vectors
// CUDA Kernel for vector addition
__global__ void vectorAdd(int* A, int* B, int* C, int n) {
int i = threadIdx.x + blockIdx.x * blockDim.x ;
C[i] = A[i] + B[i];
}
int main() {
//// Step 1 Allocate memory space
int* A, * B, * C; // Host vectors
int* d_A, * d_B, * d_C; // Device vectors
int size = SIZE * sizeof(int);
// Step 2 --> Allocate and initialize host vectors
A = (int*)malloc(size);
B = (int*)malloc(size);
C = (int*)malloc(size);
// Step 3 --> Allocate device vectors
cudaMalloc((void**)&d_A, size);
cudaMalloc((void**)&d_B, size);
cudaMalloc((void**)&d_C, size);
// Step 4 --> initialize the inputs
for (int i = 0; i < SIZE; i++) {
A[i] = i;
B[i] = SIZE - i;
}
cudaMemcpy(d_A, A, size, cudaMemcpyHostToDevice);
cudaMemcpy(d_B, B, size, cudaMemcpyHostToDevice);
// Step 5 --> Launch the Vector Add CUDA Kernel 2 blocks
vectorAdd <<<2, 1024 >>> (d_A, d_B, d_C, SIZE);
// Step 6 --> Copy result back to host
cudaMemcpy(C, d_C, size, cudaMemcpyDeviceToHost);
printf("\nExecution finished\n");
for (int i = 0; i < SIZE; i++) {
printf("%d + %d = %d ", A[i], B[i], C[i]);
printf("\n");
}
// Step 7 Cleanup
cudaFree(d_A);
cudaFree(d_B);
cudaFree(d_C);
free(A);
free(B);
free(C);
return 0;
}
Explain how the Cuda runtime apis provide a high level interface to query gpu properties, enumerate devices, and print metrics such as name, memory, and compute capability.
Analyze how varying the CUDA block size impacts performance metrics for a vector add kernel on NVIDIA GPUs, including execution time, active cycles, L1/L2 hit rates, occupancy, and memory throughput.
Learn to perform two-dimensional matrix addition on NVIDIA GPUs by using 2D blocks and grids, mapping thread and block IDs to memory indices and computing element-wise sums.
Learn how shared memory serves as a programmable software cache in Nvidia GPUs, how it blends with the L1 and L2 caches, and how bank conflicts influence performance.
Use the Nvidia Insight integration debugging tool in Visual Studio to set breakpoints, inspect memory, registers, and variables, and observe GPU kernel execution and disassembly for vector addition and reduction.
Explore the vector reduction baseline using global memory, summing a vector via a tree-based, multi-step process across threads and blocks with partial sums and kernels.
Explore implementing and profiling a multi-stage vector reduction in cuda, validating gpu results against a cpu reduction, with cpu and device memory management, kernel launches, and profiling insights.
Examine the race condition in cuda parallel reductions and how the debugging option (-G/-g) and device optimizations alter output across linux and windows using nvcc.
Increase thread utilization in a CUDA vector reduction by assigning more elements per thread, reducing grid size, and applying a two-step reduction to boost occupancy and performance.
Explore how shuffle operations enable inter-thread communication within a warp to optimize vector reductions, leveraging registers and shared memory to boost CUDA kernel performance on NVIDIA GPUs.
https://www.nvidia.com/en-us/on-demand/session/iscdigital2021-iscd2105/
https://www.nvidia.com/en-us/on-demand/session/gtcspring21-s32062/
This hands-on course teaches you how to unlock the huge parallel-processing power of modern GPUs with CUDA. You’ll start with the fundamentals of GPU hardware, trace the evolution of flagship architectures (Fermi → Pascal → Volta → Ampere → Hopper), and learn—through code-along labs—how to write, profile, and optimize high-performance kernels.
This is an independent training resource. It is not sponsored by, endorsed by, or otherwise affiliated with NVIDIA Corporation. “CUDA”, “Nsight”, and the architecture codenames are trademarks of NVIDIA and are used here only as factual references.
What you’ll master
GPU vs. CPU fundamentals – why GPUs dominate data-parallel workloads.
Generational design advances – the hardware features that matter most for performance.
CUDA toolkit installation – Windows, Linux, and WSL, plus first-run sanity checks.
Core CUDA concepts – threads, blocks, grids, and the memory hierarchy, built up with labs such as vector addition.
Profiling & tuning with Nsight Compute / nvprof – measure occupancy, hide latency, and break bottlenecks.
2-D indexing for matrices – write efficient kernels for real-world linear-algebra tasks.
Optimization playbook – handle non-power-of-two data, leverage shared memory, maximize bandwidth, and minimize warp divergence.
Robust debugging & error handling – use runtime-API checks to ship production-ready code.
By the end, you’ll be able to design, analyze, and fine-tune CUDA kernels that run efficiently on today’s GPUs—equipping you to tackle demanding scientific, engineering, and AI workloads.