1. 程式人生 > 其它 >c++ nvcc編譯CUDA程式入門示例

c++ nvcc編譯CUDA程式入門示例

 

#include<stdio.h>

__global__ void helloFromGPU(void)
{
  printf("Hello World from GPU!\n");
}

int main(void)
{
  printf("Hello World from CPU!\n");

  helloFromGPU<<<1,10>>>();
  cudaDeviceReset();
  return 0;
}

 其中__global__表示後面的函式交由GPU處理,通常GPU程式設計包含以下五步
(1)分配GPU記憶體
(2)將CPU的內容拷貝給GPU記憶體
(3)呼叫CUDA的核心函式進行處理
(4)將GPU處理完的資料拷貝給CPU
(5)釋放GPU的記憶體

上述程式碼中__global__之後的內容為核心函式<<<>>>代表從主執行緒到裝置端程式碼的呼叫,
裡面的引數10代表呼叫10個執行緒。
開啟終端,進入cu檔案所在的資料夾輸入

nvcc -o helloworld helloworld.cu
1
輸出結果應為
Hello World from CPU!
Hello World from GPU!
Hello World from GPU!
Hello World from GPU!
Hello World from GPU!
Hello World from GPU!
Hello World from GPU!
Hello World from GPU!
Hello World from GPU!
Hello World from GPU!
Hello World from GPU!

這次做一下矩陣加法運算,程式碼如下:

#include <iostream>
#include <cuda_runtime.h>

using namespace std;

__global__ void add(int *a, int *b, int *c, int n)
{
    int index = threadIdx.x + blockIdx.x * blockDim.x;
    if (index < n) {
        c[index] = a[index] + b[index];
    }
}

void random_ints(int* a, int n)
{
    for (int i = 0; i < n; ++i)
        a[i] = rand();
}

int main()
{
    int n = (2048 * 2048);
    int threads_per_block = 512;
    int *a, *b, *c;
    int *d_a, *d_b, *d_c;

    int size = n * sizeof(int);
    cudaMalloc((void**)&d_a, size);
    cudaMalloc((void**)&d_b, size);
    cudaMalloc((void**)&d_c, size);

    a = (int*)malloc(size);
    random_ints(a, n);
    b = (int*)malloc(size);
    random_ints(b, n);
    c = (int*)malloc(size);
    cudaMemcpy(d_a, a, size, cudaMemcpyHostToDevice);
    cudaMemcpy(d_b, b, size, cudaMemcpyHostToDevice);

    add<<<(n + threads_per_block - 1)/threads_per_block, threads_per_block>>>(d_a, d_b, d_c, n);

    cudaMemcpy(c, d_c, size, cudaMemcpyDeviceToHost);

    cudaFree(d_a);
    cudaFree(d_b);
    cudaFree(d_c);
    
    for (int i = 0; i < n; ++i) {
        cout << c[i] << ",";
    }
    cout << endl;
    cout << cudaGetErrorString(cudaGetLastError()) << endl;

    free(a);
    free(b);
    free(c);

    return 0;
}

 

示例雖小,五臟俱全。

流程梳理如下:

  • 準備待處理資料
  • 在device上分配儲存空間
  • 把資料從host拷貝到device
  • 執行device運算
  • 把結果從device拷貝回host
  • 結束後釋放device空間
  • 回收host資源

更具體的細節後續部落格中介紹。