Archive

Posts Tagged ‘CUDA SDK’

ขั้นตอนการติดตั้ง CUDA Toolkit และ NVIDIA CUDA SDK

December 13, 2009 Leave a comment

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;
}

Categories: Parallel Programming Tags: , , ,