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 在进行大量重复运算的性能优势。

相关推荐
无敌小茶1 小时前
Linux学习笔记之动静态库
linux·笔记
程序员JerrySUN2 小时前
驱动开发硬核特训 · Day 21(上篇) 抽象理解 Linux 子系统:内核工程师的视角
java·linux·驱动开发
雨声不在2 小时前
debian切换用户
linux·服务器·debian
不知名。。。。。。。。2 小时前
Linux—— 版本控制器Git
linux·运维·git
内网渗透3 小时前
OpenWrt 与 Docker:打造轻量级容器化应用平台技术分享
linux·docker·容器·openwrt·软路由
易保山4 小时前
MIT6.S081 - Lab11 networking(网络栈)
linux·操作系统·c
2302_799525744 小时前
【Linux】第十二章 安装和更新软件包
linux·运维·服务器
ImAlex5 小时前
Linux脚本实现自动化运维任务实战案例:系统自动备份、日志轮转、系统更新、资源监控、自动化定时任务调度
linux·运维
杨凯凡5 小时前
Linux日志分析:安全运维与故障诊断全解析
linux·运维·服务器
愚润求学5 小时前
【Linux】进程优先级和进程切换
linux·运维·服务器·c++·笔记