ขั้นตอนการติดตั้ง CUDA Toolkit และ NVIDIA CUDA SDK
1. หลังจากที่ Log in เข้าไปที่เครื่องเซิฟเวอร์แล้ว ทำการสร้างไดเรคเทอรี่ส่วนตัวขึ้นมา (ในที่นี้จะเก็บไว้ที่ /tmp/4909611727) ทำการคัดลอกไฟล์ cudatoolkit_2.3_linux_64_ubuntu9.04.run และ cudasdk_2.3_linux.run จาก /home/kasidit มาไว้ยังไดเรคเทอรี่ที่สร้างขึ้น
2. ติดตั้ง CUDA Toolkit ด้วยคำสั่ง sh cudatoolkit_2.3_linux_64_ubuntu9.04.run จากนั้นโปรแกรมจะถามถึง path ที่ต้องการจะใช้ติดตั้ง พิมพ์ /tmp/4909611727 ลงไป
3. คอมไพเลอร์ของ CUDA หรือ nvcc นั้นจะเก็บไว้ที่ /tmp/4909611727/cuda/bin ให้ตั้งค่าของ $PATH และ $LD_LIBRARY_PATH ดังนี้
export PATH=/tmp/4909611727/cuda/bin:$PATH
export LD_LIBRARY_PATH=/tmp/4909611727/cuda/lib64:$LD_LIBRARY_PATH
4. ทดสอบว่าสามารถใช้งาน nvcc ได้ด้วยการพิมพ์คำสั่ง nvcc –version ซึ่งจะได้ผลลัพท์ดังนี้
5. ติดตั้ง NVIDIA CUDA SDK ด้วยคำสั่ง sh cudasdk_2.3_linux.run โปรแกรมจะถามถึง path ที่จะใช้ติดตั้ง ซึ่งถ้าไม่ใส่จะถูกกำหนดให้เป็น NVIDIA_GPU_Computing_SDK แต่ในที่นี้จะกำหนดให้เป็น /tmp/4909611727/NVIDAI_CUDA_SDK
6. คอมไพล์ไฟล์ตัวอย่างที่มากับ NVIDIA CUDA SDK ด้วยการเข้าไปที่ /tmp/4909611727/NVIDIA_CUDA_SDK/C แล้วใช้คำสั่ง make
7. ทดสอบโปรแกรมด้วยการรันโปรแกรมตัวอย่างที่อยู่ที่ /tmp/4909611727/NVIDIA_CUDA_SDK/C/bin/linux/release ซึ่งโปรแกรมตัวอย่างที่จะทดสอบคือ deviceQuery และ bandwidthTest
deviceQuery
โปรแกรม deviceQuery เป็นโปรแกรมที่ใช้แสดงคุณลักษณะของกราฟิกการ์ดที่ใช้ ซึ่งผลลัพธ์จากการรันโปรแกรม deviceQuery เป็นดังต่อไปนี้
bandwidthTest
โปรแกรม bandwidthTest จะแสดงให้เห็นถึงความสามารถในการส่งข้อมูลแบบต่างๆระหว่างหน่วยความจำหลัก และหน่วยความจำ Global ของ GPU ทดสอบโดยการส่งข้อมูลขนาด 32 MB ผลได้เป็นดังโปรแกรม
Vector Addition
เขียนโปรแกรมบวกเวกเตอร์ เซฟด้วยชื่อไฟล์ vecadd.cu แล้วทำการคัดลอกไปยังเครื่องเซิฟเวอร์ และคอมไพล์ด้วยคำสั่ง nvcc vecadd.cu และรันโปรแกรมจะได้ผลลัพท์ออกมาดังนี้
โค้ดของโปรแกรมนี้คือ
#include <stdio.h>
__global__ void VecAdd(float *A, float *B, float *C, int N){
int idx = (blockIdx.x * blockDim.x) + threadIdx.x;
if(idx<N){
C[idx] = A[idx] + B[idx];
}
}
int main(){
float *h_A, *h_B, *h_C;
float *d_A, *d_B, *d_C;
int N = 200000;
int size = sizeof(float) * N;
int threadPerBlock = 512;
int blockPerGrid = (N + threadPerBlock -1) / threadPerBlock;
// Allocate host and device memory
h_A = (float*)malloc(size); h_B = (float*)malloc(size); h_C = (float*)malloc(size);
cudaMalloc((void**)&d_A, size); cudaMalloc((void**)&d_B, size); cudaMalloc((void**)&d_C, size);
// Initial value on vector A and B
for(int i=0;i<N;i++)
h_A[i] = rand()/200, h_B[i] = rand()/200;
// Copy vector A and B to device
cudaMemcpy(d_A, h_A, size, cudaMemcpyHostToDevice);
cudaMemcpy(d_B, h_B, size, cudaMemcpyHostToDevice);
// Call kernel
VecAdd<<< blockPerGrid, threadPerBlock >>>(d_A, d_B, d_C, N);
// Copy back vector C
cudaMemcpy(h_C, d_C, size, cudaMemcpyDeviceToHost);
printf("%s\n", cudaGetErrorString( cudaGetLastError() ) );
printf("Threads per block = %d\nBlocks per grid = %d\n", threadPerBlock, blockPerGrid);
printf("Vector size = %d\nMemory used = %f MB\n", N, 3 * size / 1024.0 / 1024);
// Deallocate host and device memory
free(h_A); free(h_B); free(h_C);
cudaFree(d_A); cudaFree(d_B); cudaFree(d_C);
return 0;
}