CUDA

CUDA 简介

CUDA(Compute Unified Device Architecture,统一计算架构)是由 NVIDIA 开发的并行计算平台和编程模型。它允许开发人员利用 NVIDIA GPU 的并行计算能力来加速应用程序的执行。

CUDA 使开发人员能够使用类似 C 语言的编程语言来写代码,并通过 CUDA 编译器将其编译成可以在 GPU 上运行的代码。

CUDA的主要组成部分包括:

  • CUDA 编程模型:允许开发人员使用 C 语言或 C++ 来编写代码,并通过特定的扩展和语法来利用GPU的并行计算能力。
  • CUDA 运行时 API:提供了一系列的函数和接口,用于在主机 CPU 和 GPU 之间进行数据传输、管理设备内存、启动并行计算任务等。
  • CUDA 工具集:包括了编译器、调试器、性能分析器等工具,帮助开发人员进行 CUDA 程序的开发、调试和优化。
  • CUDA 库:包括了一系列针对特定计算任务优化的库函数,例如线性代数、图像处理等。

通过 CUDA,开发人员可以利用 GPU 的大规模并行计算能力来加速各种类型的应用程序,包括科学计算、深度学习、图形渲染等领域的应用。

示例

add.cu

c 复制代码
#include <stdio.h>

__global__ void add(int a, int b, int *c) {
    *c = a + b;
}

int main() {
    int c;
    int *d_c;

    // Allocate memory on the device
    cudaMalloc((void **)&d_c, sizeof(int));

    // Launch the kernel with one thread
    add<<<1, 1>>>(2, 7, d_c);

    // Copy the result back to the host
    cudaMemcpy(&c, d_c, sizeof(int), cudaMemcpyDeviceToHost);

    // Free device memory
    cudaFree(d_c);

    // Print the result
    printf("2 + 7 = %d\n", c);

    return 0;
}
bash 复制代码
nvidia@nvidia-desktop:~$ nvcc add.cu -o add.out
nvidia@nvidia-desktop:~$ ./add.out 
2 + 7 = 9

性能对比

实验环境:

平台:NVIDIA Jetson AGX Orin Developer Kit - Jetpack 6.0

内存:32GB(CPU 和 GPU 共享该物理内存)

CPU:12 核 Cortex-A78,2.2GHz

GPU:2048核,930MHz(最大频率 1.3GHz)

AI 性能:275 TOPS

vector_add_4.cu

c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <cuda_runtime.h>
#include <time.h>

// CUDA kernel for vector addition
__global__ void vector_add(const float* A, const float* B, float* C, int N) {
    int i = blockDim.x * blockIdx.x + threadIdx.x;
    if (i < N) {
        C[i] = A[i] + B[i];
    }
}

// CPU implementation of vector addition
void vector_add_cpu(const float* A, const float* B, float* C, int N) {
    for (int i = 0; i < N; ++i) {
        C[i] = A[i] + B[i];
    }
}

// Function to measure elapsed time
double get_elapsed_time(struct timespec* start, struct timespec* end) {
    double start_sec = start->tv_sec + start->tv_nsec / 1.0e9;
    double end_sec = end->tv_sec + end->tv_nsec / 1.0e9;
    return end_sec - start_sec;
}

int main() {
    int N = 100000000;
    size_t size = N * sizeof(float);

    // Allocate memory on host
    float *h_A = (float*)malloc(size);
    float *h_B = (float*)malloc(size);
    float *h_C = (float*)malloc(size);
    float *h_C_GPU = (float*)malloc(size);

    // Initialize vectors
    for (int i = 0; i < N; ++i) {
        h_A[i] = (float)i;
        h_B[i] = (float)(i * 2);
    }

    // Measure CPU execution time
    struct timespec start_cpu, end_cpu;
    clock_gettime(CLOCK_MONOTONIC, &start_cpu);
    vector_add_cpu(h_A, h_B, h_C, N);
    clock_gettime(CLOCK_MONOTONIC, &end_cpu);
    double duration_cpu = get_elapsed_time(&start_cpu, &end_cpu);
    printf("CPU time: %f ms\n", duration_cpu * 1000);

    // Allocate memory on device
    float *d_A, *d_B, *d_C;
    cudaMalloc(&d_A, size);
    cudaMalloc(&d_B, size);
    cudaMalloc(&d_C, size);

    // Copy vectors from host to device
    cudaMemcpy(d_A, h_A, size, cudaMemcpyHostToDevice);
    cudaMemcpy(d_B, h_B, size, cudaMemcpyHostToDevice);

    // Measure GPU execution time
    int threads_per_block = 256;
    int blocks_per_grid = (N + threads_per_block - 1) / threads_per_block;

    struct timespec start_gpu, end_gpu;
    clock_gettime(CLOCK_MONOTONIC, &start_gpu);
    vector_add<<<blocks_per_grid, threads_per_block>>>(d_A, d_B, d_C, N);
    cudaDeviceSynchronize(); // Ensure the kernel has finished
    clock_gettime(CLOCK_MONOTONIC, &end_gpu);
    double duration_gpu = get_elapsed_time(&start_gpu, &end_gpu);
    printf("GPU time: %f ms\n", duration_gpu * 1000);

    // Copy result from device to host
    cudaMemcpy(h_C_GPU, d_C, size, cudaMemcpyDeviceToHost);

    // Verify the result
    int match = 1;
    for (int i = 0; i < N; ++i) {
        if (h_C[i] != h_C_GPU[i]) {
            match = 0;
            break;
        }
    }
    if (match) {
        printf("Results match!\n");
    } else {
        printf("Results don't match!\n");
    }

    // Clean up
    free(h_A);
    free(h_B);
    free(h_C);
    free(h_C_GPU);
    cudaFree(d_A);
    cudaFree(d_B);
    cudaFree(d_C);

    return 0;
}
bash 复制代码
nvidia@nvidia-desktop:~/cuda$ nvcc vector_add_4.cu -o vector_add_4.out
nvidia@nvidia-desktop:~/cuda$ ./vector_add_4.out 
CPU time: 353.779487 ms
GPU time: 9.406352 ms
Results match!
nvidia@nvidia-desktop:~/cuda$ ./vector_add_4.out 
CPU time: 354.594090 ms
GPU time: 9.629491 ms
Results match!
nvidia@nvidia-desktop:~/cuda$ ./vector_add_4.out 
CPU time: 354.699086 ms
GPU time: 9.630452 ms
Results match!
nvidia@nvidia-desktop:~/cuda$ ./vector_add_4.out 
CPU time: 353.854822 ms
GPU time: 9.317967 ms
Results match!
nvidia@nvidia-desktop:~/cuda$ ./vector_add_4.out 
CPU time: 353.836809 ms
GPU time: 9.618131 ms
Results match!
nvidia@nvidia-desktop:~/cuda$ ./vector_add_4.out 
CPU time: 354.636534 ms
GPU time: 9.556850 ms
Results match!

执行 1 亿次加法运算,CPU 耗时 350ms 左右,GPU 耗时 9ms 左右,可以看到 GPU 在进行大量重复运算的性能优势。

相关推荐
不想学习!!5 分钟前
linux之进程控制
java·linux·服务器
良许Linux6 分钟前
学电子信息工程时你遇到什么相见恨晚的网站和学习方法?
linux
良许Linux9 分钟前
一个人离职前有什么征兆?
linux
神经毒素14 分钟前
WEB安全--文件上传漏洞--36C3 CTF includer bypass
linux·安全·web安全
良许Linux19 分钟前
单片机、嵌入式的大神都平时浏览什么网站?
linux
kfepiza23 分钟前
`accept_ra` 和 `autoconf` 和 `forwarding` 的关系 笔记250404
linux·网络·笔记·tcp/ip·智能路由器·ip·tcp
DADIAN_GONG32 分钟前
incomplete command on Huawei switch
linux·运维·华为
Once_day40 分钟前
Linux错误(6)X64向量指令访问地址未对齐引起SIGSEGV
linux·c++·sse·x64·sigsegv·xmm0
Tee xm1 小时前
清晰易懂的 Flutter 卸载和清理教程
linux·windows·flutter·macos
小镇青年达师傅1 小时前
System V信号量 vs. POSIX信号量:核心区别与选型指南
linux·嵌入式·多线程·系统编程