1.基本流程
cuda代碼(.cu)的目的是並行運算。只要在c/c++代碼中調用以 __ global__爲關鍵字修飾的函數( __ global __ void function( type *InputArrayA, type *InputArrayB, type *OutputArrayA) ),稱爲核函數,代碼經nvcc編譯,識別到核函數就會編譯成gpu指令碼; 調用該函數時,要在函數名稱加上 <<<blocksPerGrid, threadsPerBlock>>> ( function<<<blocksPerGrid, threadsPerBlock>>>( type *InputArrayA, type *InputArrayB, type *OutputArrayA) )。不過,gpu 只能操作gpu上的變量,所以在調用 __ global __ 函數之前,先用 cudaMalloc 申請好在cuda變量內存(__global函數的參數:input array,output array),並用 cudaMemcpy (cudaMemcpyHostToDevice) 賦值輸入array。待函數執行完成後,執行結果保存在輸出array中,用 cudaMemcpy (cudaMemcpyDeviceToHost) 把執行結果從gpu內存中copy到cpu中,並行計算完成,用 cudaFree 釋放之前申請的cuda變量內存。 以上就是cpu代碼中調用gpu的流程。
1.1 blocksPerGrid, threadsPerBlock 說明
調用 cuda 核函數需要指定調用多少個block,每個block包含多少個thread。其中,多個block組成一個 grid . 共調用了 blocksPerGrid*threadsPerBlock 個並行執行的線程,所以要在cuda核函數中明確的指定每個線程執行時對應的array index。注意:thread, block有.x, .y二維數據,但有時只用其中一維.x 。下面將給出一個簡單的demo,執行 C=A+B ( c[i] = a[i] + b[i] )運算。
example1: naive_add.cu
#include "../common/book.h"
#define N 10
__global__ void add( int *a, int *b, int *c )
{
int tid = blockIdx.x; // this thread handles the data at its thread id
if (tid < N)
c[tid] = a[tid] + b[tid];
}
int main( void )
{
int a[N], b[N], c[N];
int *dev_a, *dev_b, *dev_c;
// allocate the memory on the GPU
HANDLE_ERROR( cudaMalloc( (void**)&dev_a, N * sizeof(int) ) );
HANDLE_ERROR( cudaMalloc( (void**)&dev_b, N * sizeof(int) ) );
HANDLE_ERROR( cudaMalloc( (void**)&dev_c, N * sizeof(int) ) );
// fill the arrays 'a' and 'b' on the CPU
for (int i=0; i<N; i++)
{
a[i] = -i;
b[i] = i * i;
}
// copy the arrays 'a' and 'b' to the GPU
HANDLE_ERROR( cudaMemcpy( dev_a, a, N * sizeof(int),
cudaMemcpyHostToDevice ) );
HANDLE_ERROR( cudaMemcpy( dev_b, b, N * sizeof(int),
cudaMemcpyHostToDevice ) );
//N blocks, 1 thread per block for N length arrays parallel computation(add)
add<<<N,1>>>( dev_a, dev_b, dev_c );
// copy the array 'c' back from the GPU to the CPU
HANDLE_ERROR( cudaMemcpy( c, dev_c, N * sizeof(int),
cudaMemcpyDeviceToHost ) );
// display the results
for (int i=0; i<N; i++)
{
printf( "%d + %d = %d\n", a[i], b[i], c[i] );
}
// free the memory allocated on the GPU
HANDLE_ERROR( cudaFree( dev_a ) );
HANDLE_ERROR( cudaFree( dev_b ) );
HANDLE_ERROR( cudaFree( dev_c ) );
return 0;
}