Tutorial Pemrograman CUDA – Inisialisasi

Pada artikel ini, saya akan mengulas salah satu fase dari pemrograman komputasi pararel menggunakan CUDA API, yaitu Inisialisasi Divais CUDA. Fase ini umumnya dijalankan aplikasi di awal – awal sebelum aplikasi mengeksekusi kernel – kernel CUDA ( Misal di baris – baris awal implementasi method main ). Tujuannya adalah untuk mendeteksi ada/tidaknya divais yang mendukung CUDA ( VGA/GPU Nvidia GeForce 8xxx keatas ) serta memilih divais CUDA yang akan digunakan oleh API CUDA. CUDA API memiliki 2 cita rasa , yaitu Driver API & CUDA C. Mengingat kompleksnya ( low level )Driver API & motivasi saya yang ingin memberdaya gunakan pengetahuan bahasa C saya, maka di tutorial ini ( & yang akan datang ), saya memilih menggunakan CUDA C sebagai API di kode tutorial ini.

Prasyarat

  • Pengetahuan pemrograman C dasar ( forward declaration, method, pointer, passing method parameter by reference, header & source file, #include directive, dsb )
  • Visual Studio 2008 SP1 ( atau/dan Visual Studio 2010) dengan Visual C++ terinstall di dalamnya.
  • CUDA Toolkit versi 3.2 atau lebih tinggi. Untuk tutorial instalasi nya dapat di simak di artikel ini.

Mari kita mulai

    • Method InitializeCudaDevice

Kita akan mendefinisikan kode ini sebagai method C global, dengan nama InitializeCudaDevice. Berikut adalah deklarasi method ini:

// Forward declarations
bool InitializeCudaDevice( int* numberDevices );

Tulis kode di atas pada file header baru (.h), beri nama sembarang ( misal: CudaUtility.h ). Method ini mengembalikan nilai boolean true bila inisialisasi divais CUDA berhasil lalu memilih divais pertama sebagai divais yang akan di gunakan CUDA API. Parameter pass-by-reference ( pointer integer ) numberDevices akan di isi jumlah divais CUDA yang terdeteksi bila inisialisasi berhasil ( misal : *numberDevices = 2 bila terdeteksi 2 GPU GeForce terinstal ).

Berikut adalah pseudocode dari implementasi method ini:

1. Dapatkan jumlah CUDA devices, bila tidak ada CUDA Devices yang terpasang/gagal maka kembalikan nilai false.

2. Set device CUDA pertama untuk di gunakan kernel CUDA, bila gagal kembalikan nilai false.

3. Kembalikan nilai true, sampai disini dapat di nyatakan bahwa inisialisasi divais CUDA telah berhasil.

Pertama kali, tambahkan file source code C++ baru (.cpp ), beri nama sembarang ( misal: CudaUtility.cpp ). Tulis kode deklarasi penggunaan file header kita di atas dan CUDA runtime API (<cuda_runtime_api.h>). Tulis juga kerangka implementasi method InitializeCudaDevice ini.

#include &lt;cuda_runtime_api.h&gt;
#include "CudaUtility.h";

///
/// Initialize CUDA
/// Returns TRUE if initialization is success, otherwise FALSE.
///
bool InitializeCudaDevice( int* numberDevices ){
	// Get number of CUDA Supported device

	// Set device 0 to be used as current GPU's execution

	// Initialization is success.
	return true;
};

Di dalam method ini, tulis kode untuk mendapatkan jumlah divais CUDA yg terpasang dengan memanggil method CUDA API cudaError_t cudaGetDeviceCount(int* numberDevices). Method ini akan mengembalikan nilai enumerasi cudaSuccess bila berhasil dan parameter pass-by-reference numberDevices akan terisi jumlah divais CUDA yang dapat dikenali. Pada baris ini, kita akan check apakah pemanggilan method cudaGetDeviceCount berhasil/tidak dan apakah jumlah divais CUDA yg dapat dikenali lebih dari 0 / sebaliknya. Bila 2 kondisi ini tidak terpenuhi, maka dapat kita nyatakan inisialisasi gagal.

	// Get number of CUDA Supported device
	if ( ( cudaGetDeviceCount(numberDevices) != cudaSuccess ) || ( *numberDevices  &lt; 1) ){
		// If there is no CUDA Supported device presents, return FALSE from here.
		return false;
	}

Langkah selanjutnya adalah memanggil CUDA API (cudaError_t cudaSetDevice( int deviceId )) untuk memilih divais CUDA pertama ( divais 0 ) sebagai divais yang akan di gunakan oleh CUDA API dan kernel – kernel CUDA di dalam aplikasi kita nantinya. Bila pemanggilan method ini mengembalikan nilai yang selain cudaSuccess, dapat kita nyatakan inisialisasi gagal.

	// Set device 0 to be used as current GPU's execution
	if ( cudaSetDevice(0) != cudaSuccess ){
		// Unable to use 1st CUDA Device
		return false;
	}

Berikut implementasi lengkap method inisialisasi divais CUDA ini

#include &lt;cuda_runtime_api.h&gt;
#include "CudaUtility.h";

///
/// Initialize CUDA
/// Returns TRUE if initialization is success, otherwise FALSE.
///
bool InitializeCudaDevice( int* numberDevices ){
	// Get number of CUDA Supported device
	if ( ( cudaGetDeviceCount(numberDevices) != cudaSuccess ) || ( *numberDevices  &lt; 1) ){
		// If there is no CUDA Supported device presents, return FALSE from here.
		return false;
	}

	// Set device 0 to be used as current GPU's execution
	if ( cudaSetDevice(0) != cudaSuccess ){
		// Unable to use 1st CUDA Device
		return false;
	}

	// Initialization is success.
	return true;
};
    • Contoh penggunaan – Aplikasi .NET Command Line

Buatlah sebuah project baru di dalam visual studio .NET, pilih : Visual C++ -> CLR -> Console Application di dalam dialog new project. Set CUDA’s Customization Build, runtime library dan setting lainnya pada project ini ( di ulas di artikel ini). Buat file .h & .cpp baru dan tulis implementasi kode di atas ke dalam project ini. Berikut adalah kode contoh penggunaannya di dalam file main.cpp :

#include "stdafx.h"
#include "CudaUtility.h"

using namespace System;
using namespace System::Text;

int main(array ^args)
{
	// Initialize Cuda
	int numberOfDevices = 0;
	StringBuilder^ stringBuilder = gcnew StringBuilder();
	if ( InitializeCudaDevice(&amp;numberOfDevices) ){
		// If success , display the number of initialized devices to screen and success message
		stringBuilder-&gt;Append( L"CUDA Devices initialization is SUCCESS\n" );
		stringBuilder-&gt;Append( String::Format( L"Number of detected devices : {0}", numberOfDevices ) );
	}
	else{
		// otherwise display failed initialization's message
		stringBuilder-&gt;Append( L"Initialization is FAILED" );
	}
	stringBuilder-&gt;Append( L"\n\nPress enter to exit..." );
	Console::Write( stringBuilder-&amp;gt;ToString() );
	Console::ReadLine();
    return 0;
}

Kode keseluruhan yg di ulas dalam artikel ini dapat di ambil dari url Subversion berikut ini : http://saint.xtremecodes.asia:8080/svn/tutorial_cuda/Initialization. Selamat mencoba 🙂

Tutorial – Instalasi Nvidia CUDA Toolkit pada Visual Studio 2010

Pada artikel tutorial ini, saya akan mengulas langkah – langkah instalasi CUDA Toolkit versi 3.2 pada Visual Studio 2010. Perlu di ketahui pembaca bahwa CUDA Toolkit versi 3.2 ini di build dengan menggunakan Visual C++ runtime versi 9.0 ( terdapat pada VS .NET 2008 ). Secara default, compiler C++ di toolkit ini ( nvcc ) tidak dapat digunakan bila kita coba membuild project kita di dalam Visual C++ 2010 ( Runtime C++ yg digunakan versi 10.0). Namun kendala ini dapat diatasi dengan melakukan cara instalasi yang akan di ulas berikut ini.

Persiapan

Unduh file-file instalasi berikut ini:

Unduh installer yang sesuai dengan jenis OS & GPU yg di pakai oleh mesin anda ( 32 bit / 64 bit OS; GeForce/Quadro GPU). Untuk Parallel NSight, ada 2 installer yang harus di unduh yaitu Parallel Nsight Host dan Parallel Nsight Monitor.

Tautan pengunduhan NSight
Tautan pengunduhan NSight

Begitupun pada CUDA Toolkit, unduh installer yg sesuai dengan OS mesin anda ( 32 bit/64 bit )

Halaman unduh CUDA Toolkit
Halaman unduh CUDA Toolkit

Instalasi

Sebelum meng-instal file – file yang telah diunduh, pastikan bahwa anda sudah menginstal Visual Studio 2008 SP1 di mesin anda. Lakukanlah instalasi dengan urutan : Nsight Host -> NSight Monitor -> CUDA Toolkit 3.2. Matikan juga aplikasi Visual Studio yang aktif sebelum instalasi di mulai. Pada dialog instalasi , cukup tekan tombol Next; isi nama, email pada window registrasi dan pilih jenis instalasi Typical / Complete.

Instalasi - Jendela registrasi user
Instalasi - Jendela registrasi user

Menambahkan extensi file .cu ( kernel CUDA ) di VS .NET

Pada menu bar VS .NET, klik Tools -> Options untuk membuka jendela Options. Di jendela ini, buka node treeview Text Editor, pilih File Extension. Di textbox berlabel Extension, ketik .cu. Klik kotak kombo Editor, pilih entry Microsoft Visual C++. Klik tombol Apply. Klik tombol Ok.

Regstrasi file CUDA ( .cu ) pada VS .NET
Regstrasi file CUDA ( .cu ) pada VS .NET

Menyeting & mengkompilasi project CUDA

  • Buat solution kosong yang baru. Tambahkan project baru di dalam solusi yg di buat. Pilih jenis project CLR->Class Library untuk menanmbahkan project .NET DLL ke dalam solution. Alasan dipilihnya project .NET DLL pada tutorial ini karena penulis ingin menguji apakah solusi CUDA ini dapat di integrasikan dengan aplikasi .NET.
    Membuat project DLL .NET ke dalam solution
    Membuat project DLL .NET ke dalam solution
  • Mengaktifkan CUDA’s Build Customization – Pada menu bar VS .NET, klik Project -> Build Customizations… untuk memunculkan jendela Visual C++ Build Customization Files. Centang pilihan CUDA 3.2(.targets, props) lalu klik tombol Ok. Entry ini akan di tampilkan bila proses instalasi NSight & CUDA Tools berhasil dan sesuai dengan langkah – langkah sebelumnya.
    Mengaktifkan Custom Build CUDA pada project yang di pilih.
    Mengaktifkan Custom Build CUDA pada project yang di pilih.
  • Buka halaman property project .NET C++ -nya, pilih node Configuration Properties -> General lalu di panel kanan jendela property, ubah nilai entry Platform Toolset yang semula v100 menjadi v90. Klik tombol Apply.
    Mengubah Platform Toolset
    Mengubah Platform Toolset
  • Masih pada jendela Property Pages, pilih node Configuration Properties -> Linker -> Input, lalu di panel kanan jendela property, tambahkan nilai cudart.lib; pada entry Additional Dependencies. Klik tombol Ok pada jendela ini.
    Menambahkan referensi ke Library Runtime CUDA
    Menambahkan referensi ke Library Runtime CUDA
  • Ubah target .NET Framework project ke versi 3.5 – Unload terlebih dulu project ini dengan cara klik kanan node project, klik menu item Unload project pada pop up menu. Klik kanan kembali node project yang telah di unload, lalu klik pilihan Edit .vcxproj pada menu pop up untuk memulai editing file project ini secara manual. Ubah nilai di dalam tag xml TargetFrameworkVersion dari yang semula 4.0 ke 3.5. Save file ini lalu load kembali project ini.
    Mengubah Versi .NET Framework dari Project .NET DLL
    Mengubah Versi .NET Framework dari Project .NET DLL
  • Tambahkan file baru pada project .NET DLL ini, berekstensi .cu dengan nama sembarang ( misal: MyKernel.cu ). Biarkan kosong terlebih dahulu isi file .cu ini. Save semua perubahan, lalu build project ini. Berikut adalah isi panel output build bila kompilasi berhasil. Selamat mencoba 🙂

    1>------ Rebuild All started: Project: Excercise.Cuda.ManagedKernel, Configuration: Debug Win32 ------
    1>
    1> E:\PROJECTS\Excercise.Cuda\Excercise.Cuda.ManagedKernel>"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v3.2\\bin\nvcc.exe" -ccbin "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin" -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v3.2\\include" -G0 --keep-dir "Debug\\" -maxrregcount=32 --machine 32 --compile -D_NEXUS_DEBUG -g -Xcompiler "/EHsc /nologo /Od /Zi /MDd " -o "Debug\MathKernel.obj" "E:\PROJECTS\Excercise.Cuda\Excercise.Cuda.ManagedKernel\Kernels\MathKernel.cu" -clean
    1> Compiling CUDA source file Kernels\MathKernel.cu...
    1>
    1> E:\PROJECTS\Excercise.Cuda\Excercise.Cuda.ManagedKernel>"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v3.2\\bin\nvcc.exe" -gencode=arch=compute_10,code=\"sm_10,compute_10\" --use-local-env --cl-version 2008 -ccbin "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin" -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v3.2\\include" -G0 --keep-dir "Debug\\" -maxrregcount=32 --machine 32 --compile -D_NEXUS_DEBUG -g -Xcompiler "/EHsc /nologo /Od /Zi /MDd " -o "Debug\MathKernel.obj" "E:\PROJECTS\Excercise.Cuda\Excercise.Cuda.ManagedKernel\Kernels\MathKernel.cu"
    1> tmpxft_000010ac_00000000-11_MathKernel.ii
    1> Stdafx.cpp
    1> AssemblyInfo.cpp
    1> Generating Code...
    1> Microsoft (R) Windows (R) Resource Compiler Version 6.1.6723.1
    1>
    1> Copyright (C) Microsoft Corporation. All rights reserved.
    1>
    1>
    1> Excercise.Cuda.ManagedKernel.vcxproj -> E:\PROJECTS\Excercise.Cuda\Debug\Excercise.Cuda.ManagedKernel.dll
    ========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ==========