天天看點

CUDA GPU程式設計CUDA

文章目錄

  • CUDA
    • GPU并行化的工作流程:
    • 修飾符
      • `__global__`
      • `__host__`
      • `__device__`
    • 記憶體配置設定

CUDA

随着顯示卡的發展,GPU越來越強大,而且GPU為顯示圖像做了優化。在計算上已經超越了通用的CPU。如此強大的晶片如果隻是作為顯示卡就太浪費了,是以NVidia推出CUDA,讓顯示卡可以用于圖像計算以外的目的。

host 指代CPU及其記憶體,

device指代GPU及其記憶體。

CUDA程式中既包含host程式,又包含device程式,它們分别在CPU和GPU上運作。同時,host與device之間可以進行通信,它們之間可以進行資料拷貝。

GPU并行化的工作流程:

CPU發送一種稱為kernel的函數到GPU。

GPU同時運作該函數的多個版本,稱為threads。thread可以組合成block,一個kernel裡的所有thread稱為一個grid。

threads :thread的不同版本

block : 多個thread組成

grid:一個kernel裡的所有thread

修飾符

__host__

修飾符

__global__

修飾符

__device__

修飾符

__global__

__global__

CUDA C/C++

的函數修飾符,表示該函數為一個kernel函數,且

  1. 該函數會在

    GPU(device)

    上執行。
  2. 必須傳回

    void

  3. 由主機

    (host)

    代碼調用。
  4. 隻能被CPU調用。

在調用

kernel

函數時,函數名後的

<<<b, t>>>

  • b

    代表block的數目。
  • t

    代表每個block中thread的數目。
//kernel函數需要運作在4個block上,每個block有2個thread
__global__ void myKernel() {
	// ...
}

void main()
{
	int block,thread;
	block=4;
	thread=2;
	myKernel<<<block,thread>>>();
}
           

__host__

  • 運作在CPU上,每次調用運作一次。
  • 隻能被CPU調用。
  • 所有未顯式标明函數前置修飾符的函數均為host函數。

__device__

  • 運作在GPU上,每次調用運作一次。
  • 隻能被GPU調用。
#include <stdio.h>

__device__ int dev1() {
}
__device__ int dev2() {
}
__global__ void run10Times() {
	//your code here
	dev1();
	dev2();
	//end of your code
}

int main() {
	run10Times<<<2, 5>>>();
	printf("Hello, World!\n");
	return 0;
}
           

記憶體配置設定

cudaMalloc

配置設定裝置上的記憶體

cudaMemcpy

将不同記憶體段的資料進行拷貝

cudaFree

釋放先前在裝置上申請的記憶體空間

__host__ cudaError_t cudaMalloc (void **devPtr, size_t size)
	/*該函數主要用來配置設定裝置上的記憶體(即顯存中的記憶體)。該函數被聲明為了__host__,即表示被host所調用,即在cpu中執行的代碼所調用。
    傳回值:為cudaError_t類型,實質為cudaError的枚舉類型,其中定義了一系列的錯誤代碼。如果函數調用成功,則傳回cudaSuccess。
    第一個參數,void ** 類型,devPtr:用于接受該函數所配置設定的記憶體位址。
    第二個參數,size_t類型,size:指定配置設定記憶體的大小,機關為位元組。*/ 

__host__ cudaError_t cudaMemcpy (void *dst, const void *src, size_t count, enum cudaMemcpyKind kind)
    /*
    該函數主要用于将不同記憶體段的資料進行拷貝,記憶體可用是裝置記憶體,也可用是主機記憶體
    第一個參數,void*類型,dst:為目的記憶體位址
    第二個參數,const void *類型,src:源記憶體位址
    第三個參數,size_t類型,count:将要進行拷貝的位元組大小
    第四個參數,enum cudaMemcpyKind類型,kind:拷貝的類型,決定拷貝的方向。
    cudaMemcpyKind類型如下:cudaMemcpyHostToHost, cudaMemcpyHostToDevice, cudaMemcpyDeviceToHost, cudaMemcpyDeviceToDevice, cudaMemcpyDefault。*/ 
    
__host__ cudaError_t cudaFree (void* devPtr)
    /*該函數用來釋放先前在裝置上申請的記憶體空間(通過cudaMalloc、cudaMallocPitch等函數),注意,不能釋放通過标準庫函數malloc進行申請的記憶體。
    傳回值:為錯誤代碼的類型值。
    第一個參數,void**類型,devPtr:指向需要釋放的裝置記憶體位址。*/ 
           

cudaMemcpyKind類型如下:

cudaMemcpyHostToHost,

cudaMemcpyHostToDevice,

cudaMemcpyDeviceToHost,

cudaMemcpyDeviceToDevice,

cudaMemcpyDefault。

#include <stdio.h>
#include <stdlib.h>
#include <cuda.h>
#include <cuda_runtime.h> 

__global__ void colonel(int *a_d){
	//your code here
    *a_d = 2;
	//end of your code
}

int main(){
	int a = 0, *a_d;
	cudaMalloc((void**) &a_d, sizeof(int));
	cudaMemcpy(a_d, &a, sizeof(int), cudaMemcpyHostToDevice);
	colonel<<<1, 1>>>(a_d); 
  
	cudaMemcpy(&a, a_d, sizeof(int), cudaMemcpyDeviceToHost);

	printf("a = %d\n", a);
	cudaFree(a_d);
}
           

繼續閱讀