Освоение программирования CUDA: руководство для начинающих по ускорению графического процессора

Готовы ли вы погрузиться в захватывающий мир программирования CUDA? Пристегнитесь и будьте готовы использовать мощь вашего графического процессора для молниеносных параллельных вычислений. В этой статье блога мы рассмотрим различные методы и предоставим разговорные объяснения, а также примеры кода, которые помогут вам начать свой путь в программировании CUDA.

  1. Привет, CUDA: начнем с классического «Hello, World!» пример в CUDA. Эта простая программа демонстрирует, как инициализировать графический процессор, передавать данные в память графического процессора, выполнять ядро ​​(функцию, которая выполняется на графическом процессоре) и возвращать результаты обратно в процессор.
#include <stdio.h>
__global__ void helloCUDA()
{
    printf("Hello, CUDA!\n");
}
int main()
{
    helloCUDA<<<1, 1>>>();
    cudaDeviceSynchronize();
    return 0;
}
  1. Сложение векторов. Одной из фундаментальных концепций параллельных вычислений является параллельное выполнение операций над массивами. В этом примере мы добавим два вектора вместе с помощью CUDA.
#include <stdio.h>
__global__ void vectorAdd(int* a, int* b, int* result, int size)
{
    int tid = blockIdx.x * blockDim.x + threadIdx.x;

    if (tid < size)
        result[tid] = a[tid] + b[tid];
}
int main()
{
    int size = 1024;
    int* a, *b, *result;
    // Allocate memory on CPU
    // Initialize arrays a and b
    // Allocate memory on GPU
    // Copy data from CPU to GPU
    // Launch kernel
    // Copy result from GPU to CPU
    // Free memory on GPU and CPU
    return 0;
}
  1. Умножение матриц: CUDA особенно эффективен для выполнения ресурсоемких задач, таких как умножение матриц. В этом примере показано, как перемножить две матрицы с помощью CUDA.
#include <stdio.h>
#define N 16
__global__ void matrixMultiplication(int* a, int* b, int* result)
{
    int row = blockIdx.y * blockDim.y + threadIdx.y;
    int col = blockIdx.x * blockDim.x + threadIdx.x;
    int sum = 0;

    if (row < N && col < N) {
        for (int i = 0; i < N; i++)
            sum += a[row * N + i] * b[i * N + col];
        result[row * N + col] = sum;
    }
}
int main()
{
    int* a, *b, *result;
    // Allocate memory on CPU
    // Initialize matrices a and b
    // Allocate memory on GPU
    // Copy data from CPU to GPU
    // Define grid and block dimensions
    // Launch kernel
    // Copy result from GPU to CPU
    // Free memory on GPU and CPU
    return 0;
}
  1. Обработка изображений: CUDA может значительно ускорить задачи обработки изображений. Давайте рассмотрим простой пример преобразования изображения в оттенках серого в его негатив с помощью CUDA.
#include <stdio.h>
__global__ void imageNegate(unsigned char* image, int width, int height)
{
    int col = blockIdx.x * blockDim.x + threadIdx.x;
    int row = blockIdx.y * blockDim.y + threadIdx.y;

    if (col < width && row < height) {
        int index = row * width + col;
        image[index] = 255 - image[index];
    }
}
int main()
{
    unsigned char* image;
    int width, height;
    // Load image using a library (e.g., OpenCV)
    // Allocate memory on GPU
    // Copy image data from CPU to GPU
    // Define grid and block dimensions
    // Launch kernel
    // Copy result from GPU to CPU
    // Save image using a library
    // Free memory on GPU and CPU

    return 0;
}
  1. Сокращение. Сокращение — обычная операция в параллельных вычислениях. Он предполагает объединение данных из нескольких потоков в одно значение. Давайте посмотрим, как мы можем выполнить сокращение с помощью CUDA.
#include <stdio.h>
#define N 1024
__global__ void reduction(int* input, int* output)
{
    __shared__ int sharedData[N];
    int tid = threadIdx.x;
    int index = blockIdx.x * blockDim.x + tid;

    if (index < N)
        sharedData[tid] = input[index];
    else
        sharedData[tid] = 0;

    __syncthreads();

    for (int stride = 1; stride < blockDim.x; stride *= 2) {
        int index = 2 * stride * tid;

        if (index < blockDim.x)
            sharedData[index] += sharedData[index + stride];

        __syncthreads();
    }

    if (tid == 0)
        output[blockIdx.x] = sharedData[0];
}
int main()
{
    int* input, *output;
    // Allocate memory on CPU
    // Initialize input array
    // Allocate memory on GPU
    // Copy input data from CPU to GPU
    // Define grid and block dimensions
    // Launch kernel
    // Copy result from GPU to CPU
    // Perform final reduction on CPU
    // Free memory on GPU and CPU
    return 0;
}

Это всего лишь несколько примеров, которые помогут вам начать программировать на CUDA. Не забывайте обращаться к официальной документации CUDA и изучать более сложные методы по мере продвижения. Приятного вам программирования и наслаждайтесь невероятной мощью ускорения графического процессора!