Pengantar Komputasi Modern
Andiko Bayu Parallelism
Concept
Jeffry Akbar Pengantar
Thread Programming
Andre Purwandono Pengantar Massage
Passing, OpenMP
Alija Nur Farizi Pengantar
pemrograman CUDA GPU
Paralelism Concept
Pengertian Komputasi
Parallel
Komputasi parallel adalah salah satu teknik
melakukan komputasi secara bersamaan dengan memanfaatkan beberapa komputer
independen secara bersamaan. Ini umumnya diperlukan saat kapasitas yang
diperlukan sangat besar, baik karena harus mengelolah data dalam jumlah besar
(di industri keuangan, bioinformatika, dll) ataupun karena tuntutan proses
komputasi yang banyak.
Secara prinsip komputer parallel membagi
permasalahan sehingga menjadi lebih kecil untuk dikerjakan oleh setiap prosesor
(CPU) dalam waktu yang bersamaan/simultan (concurrent).
Komputasi parallel membutuhkan:
-
Algoritma
-
Bahasa
pemrograman
-
Compiler
Pemrograman Parallel
Di dalam komputasi parallel ada yang dinamakan
dengan pemrograman parallel. Pemrograman parallel adalah teknik pemrograman
komputer yang memungkinkan eksekusi perintah/operasi secara bersamaan, baik
dalam komputer satu (prosesor tunggal) ataupun banyak (prosesor ganda dengan
mesin parallel) CPU.
Tujuan utama dari pemrograman parallel adalah
untuk meningkatkan performa komputasi. Semakin banyak hal yang bisa dilakukan
secara bersamaan, semakin banyak pekerjaan yang bisa diselesaikan.
Bahasa Pemrograman
pada Pemrograman Parallel
- MPI
Message Passing Interface (MPI) adalah sebuah
standard pemrograman yang memungkinkan pemrogram untuk memuat sebuah aplikasi
yang dapat dijalankan secara parallel dengan spesifikasi library pemrograman
untuk meneruskan pesan (message passing), yang diajukan sebagai standar oleh
berbagai komite dari vendor, pelaksana dan pemakai. Message Passing Interface
bertugas untuk mengirim data antar komputer di dalam sistem parallel (biasanya
disebut dengan node atau host).
Kegunaan MPI:
-
Menyediakan
fungsi-fungsi untuk menukar pesan.
-
Menulis
kode parallel secara portable.
-
Mendapatkan
performa yang tinggi dalam pemrograman parallel.
-
Menghadapi
permasalahan yang melibatkan hubungan data irregular atau dinamis yang tidak
begitu cocok dengan model data parallel.
- PVM
Private Virtual Machine adalah perangkat lunak
yang memungkinkan sekumpulan komputer yang heterogen terlihat seperti satu
sistem komputer parallel dan dapat digunakan sebagai sebuah sumber daya
komputasi yang koheren.
PVM terdiri dari beberapa komponen yaitu:
-
PVM daemon
Daemon merupakan semacam program yang berjalan
di “belakang” dan biasanya menangani program dari klien. Komponen ini berada
pada setiap komputer yang terhubung dalam virtual machine.
-
PVM libraries
Komponen ini berisi rutin-rutin antarmuka
pemakai PVM untuk melakukan pengiriman pesan, pembuatan proses, koordinasi proses
dan modifikasi virtual machine.
Arsitektur Komputer
Parallel
Berdasarkan jumlah dan prinsip kerja prosesor
pada komputer parallel, A.J. Van der Steen dan J.Donggara menyebutkan terdapat
empat arsitektur utama komputer parallel menurut Flynn (1972) yaitu :
I.
SISD
(Single Instruction – Single Data)
Komputer ini memiliki hanya satu prosesor dan
satu instruksi yang dieksekusi secara serial. Komputer ini adalah tipe komputer
konvensional.
II.
SIMD
(Single Instruction – Multiple Data)
Komputer ini memiliki lebih dari satu prosesor,
tetapi hanya mengeksekusi satu instruksi secara parallel pada data yang berbeda
pada level lock-step. Komputer vektor adalah salah satu komputer yang
meggunakan arsitektur ini.
III.
MISD
(Multiple Instructions – Single Data)
Komputer ini memiliki satu prosesor dan
mengeksekusi beberapa instruksi secara parallel tetapi praktiknya tidak ada
komputer yang dibangun dengan arsitektur ini karena sistemnya tidak mudah
dipahami.
IV.
MIMD
(Multiple Instructions – Multiple Data)
Komputer ini memiliki lebih dari satu prosesor
dan mengeksekusi lebih dari satu instruksi secara parallel. Tipe komputer ini
yang paling banyak digunakan untuk membangun komputer parallel.
Pengantar Thread Programming
Dalam pemrograman komputer,
sebuah thread adalah informasi terkait dengan penggunaan sebuah program tunggal
yang dapat menangani beberapa pengguna secara bersamaan. Dari program
point-of-view, sebuah thread adalah informasi yang dibutuhkan untuk melayani
satu pengguna individu atau permintaan layanan tertentu. Jika beberapa pengguna
menggunakan program atau permintaan bersamaan dari program lain yang sedang
terjadi, thread yang dibuat dan dipelihara untuk masing-masing proses. Thread
memungkinkan program untuk mengetahui user sedang masuk didalam program secara
bergantian dan akan kembali ma
suk atas nama pengguna yang berbeda. Salah satu informasi thread disimpan dengan cara menyimpannya di daerah data khusus dan menempatkan alamat dari daerah data dalam register. Sistem operasi selalu menyimpan isi register saat program interrupted dan restores ketika memberikan program kontrol lagi.
suk atas nama pengguna yang berbeda. Salah satu informasi thread disimpan dengan cara menyimpannya di daerah data khusus dan menempatkan alamat dari daerah data dalam register. Sistem operasi selalu menyimpan isi register saat program interrupted dan restores ketika memberikan program kontrol lagi.
Sebagian besar komputer hanya
dapat mengeksekusi satu instruksi program pada satu waktu, tetapi karena mereka
beroperasi begitu cepat, mereka muncul untuk menjalankan berbagai program dan
melayani banyak pengguna secara bersamaan. Sistem operasi komputer memberikan
setiap program "giliran" pada prosesnya, maka itu memerlukan untuk
menunggu sementara program lain mendapat giliran. Masing-masing program
dipandang oleh sistem operasi sebagai suatu tugas dimana sumber daya tertentu diidentifikasi
dan terus berlangsung. Sistem operasi mengelola setiap program aplikasi dalam
sistem PC (spreadsheet, pengolah kata, browser Web) sebagai tugas terpisah dan
memungkinkan melihat dan mengontrol item pada daftar tugas. Jika program
memulai permintaan I / O, seperti membaca file atau menulis ke printer, itu
menciptakan thread. Data disimpan sebagai bagian dari thread yang memungkinkan
program yang akan masuk kembali di tempat yang tepat pada saat operasi I / O
selesai. Sementara itu, penggunaan bersamaan dari program diselenggarakan pada
thread lainnya. Sebagian besar sistem operasi saat ini menyediakan dukungan
untuk kedua multitasking dan multithreading. Mereka juga memungkinkan
multithreading dalam proses program agar sistem tersebut disimpan dan menciptakan proses baru untuk setiap thread.
Static Threading
Teknik ini biasa digunakan untuk
komputer dengan chip multiprocessors dan jenis komputer shared-memory lainnya.
Teknik ini memungkinkan thread berbagi memori yang tersedia, menggunakan
program counter dan mengeksekusi program secara independen. Sistem operasi
menempatkan satu thread pada prosesor dan menukarnya dengan thread lain yang
hendak menggunakan prosesor itu.
Mekanisme ini terhitung lambat,
karenanya disebut dengan static. Selain itu teknik ini tidak mudah diterapkan
dan rentan kesalahan. Alasannya, pembagian pekerjaan yang dinamis di antara
thread-thread menyebabkan load balancing-nya cukup rumit. Untuk memudahkannya
programmer harus menggunakan protocol komunikasi yang kompleks untuk menerapkan
scheduler load balancing. Kondisi ini mendorong pemunculan concurrency
platforms yang menyediakan layer untuk mengkoordinasi, menjadwalkan, dan
mengelola sumberdaya komputasi paralel.
Sebagian platform dibangun
sebagai runtime libraries atau sebuah bahasa pemrograman paralel lengkap dengan
compiler dan pendukung runtime-nya.
Dynamic Multithreading
Teknik ini merupakan pengembangan
dari teknik sebelumnya yang bertujuan untuk kemudahan karena dengannya
programmer tidak harus pusing dengan protokol komunikasi, load balancing, dan
kerumitan lain yang ada pada static threading. Concurrency platform ini
menyediakan scheduler yang melakukan load balacing secara otomatis. Walaupun
platformnya masih dalam pengembangan namun secara umum mendukung dua fitur :
nested parallelism dan parallel loops. Nested parallelism memungkinkan sebuah
subroutine di-spawned (ditelurkan dalam jumlah banyak seperti telur katak)
sehingga program utama tetap berjalan sementara subroutine menghitung hasilnya.
Sedangkan parallel loops seperti halnya fungsi for namun memungkinkan iterasi
loop dilakukan secara bersamaan.
Model Multi-Threading
1.
Many-to-One
-
Memetakan beberapa thread tingkatan pengguna ke sebuah thread tingkatan
kernel.
-
Pengaturan thread dilakukan dalam ruang pengguna, sehingga efisien.
-
Hanya satu thread pengguna yang dapat mengakses thread kernel pada satu
saat.
2.
One-to-One
- Memetakan setiap thread tingkatan
pengguna ke thread kernel.
- Model ini menyediakan lebih banyak
concurrency dibandingkan model Many-to-One.
3.
Many-to-Many
-
Mengelompokkan banyak thread pengguna untuk dipetakan ke thread kernel
yang jumlahnya lebih sedikit atau sama dengan tingkatan pengguna.
- Mengijinkan sistem operasi untuk
membuat sejumlah thread kernel.
Thread cancellation
Thread cancellation/ pembatalan
thread ialah pemberhentian thread sebelum tugasnya selesai. Misalnya jika dalam
program Java hendak mematikan Java Virtual Machine (JVM). Sebelum JVM
dimatikan, maka seluruh thread yang berjalan harus dihentikan terlebih dahulu.
Thread yang akan diberhentikan
disebut sebagai target thread. Pembatalan Thread terdiri dari 2 jenis:
Asynchronous cancellation: suatu thread
seketika itu juga memberhentikan target thread.
Deffered cancellation: target thread
secara perodik memeriksa apakah dia harus berhenti, cara ini memperbolehkan
target thread untuk memberhentikan dirinya sendiri secara terurut.
Pengantar Massage Passing, OpenMP
Message Passing
Message passing adalah proses
pengiriman data, dimana data dari suatu memori disalin ke memori pada prosesor
lain. Karena proses pengiriman datanya antar memori lokal maka teknik message
passing biasanya digunakan untuk model
komputasi paralel dengan memori terdistribusi. Dalam model ini, proses atau
objek dapat mengirim dan menerima pesan (sinyal, fungsi, struktur data kompleks,
atau paket data) ke proses atau objek lain.
Operasi dasar yang dibutuhkan
untuk mendukung paradigma message passing adalah send dan receive. Operasi
pengirim membutuhkan proses pengiriman untuk menspesifikasikan lokasi data, ukuran, tipe dan tujuan. Operasi
penerima harus melakukan penyesuaian dengan operasi pengirim. Konsep message
passing membuat lebih mudah untuk membangun sistem yang memodelkan atau
mensimulasikan masalah dunia nyata.
Terdapat dua metode dalam
pengiriman pesan yaitu :
Synchronous Message Passing
Sistem pengiriman pesan secara
sinkron mengharuskan pengirim dan penerima untuk menunggu satu sama lain saat
mentransfer pesan. Pengirim menunggu untuk mengirim pesan sampai penerima siap
untuk menerima pesan. Oleh karena itu tidak ada buffering. Selain itu pengirim
tidak bisa mengirim pesan untuk dirinya sendiri. (contoh: chatting)
Ansynchronous Message Passing
Sedangkan dalam komunikasi
asinkron pengirim dan penerima tidak saling menunggu dan dapat melakukan
perhitungan sendiri saat pengiriman pesan sedang dilakukan. Pengirim akan
mengirim pesan kapanpun dia mau. Pengirim tidak peduli ketika penerima belum
siap untuk menerima pesan. Oleh karena itu diperlukan buffering untuk menampung
pesan sementara sampai penerima siap menerima pesan. Selain itu pengirim dapat
pesan untuk dirinya sendiri.
Selain berdasarkan metode
pengiriman pesan diatas, pengiriman pesan (message passing) dapat dibedakan
berdasarkan jumlah penerima pesan yaitu: Point to Point dan Broadcast.
Perbedaan mendasar keduanya adalah jumlah penerima yang menerima pesan. Pada
Point to Point penerimanya tunggal sedangkan pada broadcast jumlah penerimanya
banyak. (contoh mail, bulletin board, dll).
OpenMP (Open Multiprocessing)
OpenMP merupakan standar yang
digunakan untuk pemrograman paralel multithreading pada arsitektur shared memory.
OpenMP adalah sebuah antarmuka pemrograman aplikasi (API) untuk menulis
aplikasi multithread, berupa satu set direktif compiler dan library untuk
pemrograman aplikasi paralel yang menyederhanakan penulisan program multithread
pada C, C++, dan Fortran pada berbagai arsitektur, termasuk Unix dan Microsoft
Windows platform. Program multithread dapat ditulis dalam berbagai cara.
Beberapa diantaranya memungkinkan untuk melakukan interaksi yang kompleks antar
thread. OpenMP mencoba untuk memberikan kemudahan pemrograman serta membantu
dalam menghindari kesalahan program, melalui pendekatan terstruktur. Pendekatan
ini dikenal sebagai model pemrograman fork-join. OpenMP dikelola oleh nirlaba
teknologi konsorsium OpenMP Arsitektur Review Board (ARB atau OpenMP),
bersama-sama didefinisikan oleh sekelompok perangkat keras komputer utama dan
vendor perangkat lunak, termasuk AMD, IBM, Intel, Cray, HP, Fujitsu, Nvidia,
NEC, Microsoft, Texas Instruments, Oracle Corporation, dan banyak lagi.
Pengantar pemrograman CUDA GPU
CUDA (Compute
Unified Device Architecture) adalah suatu skema yang dibuat oleh NVIDIA agar
NVIDIA selaku GPU (Graphic Processing Unit) mampu
melakukan komputasi tidak hanya untuk pengolahan grafis namun juga untuk tujuan
umum. Jadi, dengan CUDA, kita dapat memanfaatkan cukup banyak processor yang
dimiliki oleh NVIDIA untuk berbagai perhitungan. GPU yang ada saat ini
seperti ATI pun sudah memiliki banyak processor di dalamnya.
Pada ATI, skema yang mereka bangun disebut ATI Stream. Saat ini pemrograman
paralel menjadi sangat penting karena kebutuhan kemampuan komputasi komputer
yang terus meningkat seperti kemampuan multitasking dan pengolahan
grafis yang andal. Metode saat ini dalam peningkatan peforma komputer juga
berbeda dengan masa lampau dimana peningkatan clock dari processor yang
diutamakan.
Peningkatan clock juga
dibatasi oleh kemampuan fisik dari perangkat digital yaitu persoalan daya dan
panas. Pada 2005 berbagai industri komputer mulai menawakan komputer dengan
beberapa core mulai dari 2, 3, 4, 6, dst. Pada awal
perkembangan GPU dengan banyak core, pemanfaatan GPU hanya
dapat dilakukan dengan antarmuka seperti OpenGL dan DirectX dimana antarmuka
tersebut dikhususkan hanya untuk pengolahan grafis.
Seri-seri terbaru dari NVIDIA
saat ini telah mendukung CUDA tepatnya keluaran setelah tahun 2006. Untuk
daftar dari seri yang mendukung CUDA dapat dilihat pada http://nvidia.com/cuda. Sebagai
tahap awal dalam belajar pemrograman paralel dengan memanfaatkan CUDA sebaiknya
menggunakan bahasa pemrograman C atau C++. CUDA C telah menjadi bahasa
pemrograman khusus pertama yang dikembangkan oleh suatu perusahaan GPU untuk
memfasilitasi general-purpose computing pada GPU. Beberapa hal
yang perlu dipersiapkan dalam penggunaan CUDA C untuk membuat suatu aplikasi
adalah sebagai berikut.
- CUDA-enabled graphics processor
- NVIDIA device driver
- CUDA development toolkit
- Standard C compiler
Kebutuhan seperti toolkit dan driver dapat
diunduh di
http://developer.nvidia.com/cuda-downloads.
CUDA C menyediakan kebutuhan tersebut untuk Windows, Linux, dan Mac. Jika telah
memasang CUDA toolkit pada komputer Anda maka akan ada
aplikasi compiler yang dapat Anda gunakan yaitu nvcc. Selain
itu, jika Anda menggunakan Windows sebaiknya Anda juga memasang Visual Studio
untuk kemudahan pembuatan aplikasi dan ada program bernama cl.exe dari
Visual Studio yang diperlukan dalam kompilasi.
Hal khusus dalam kode program
yang menggunakan CUDA C adalah adanya kernel call. Sebagai
contoh adalah cuplikan kode berikut.
#include
__global__ void kernel( void ) {
}
int main( void ) {
kernel<<<1>>>();
printf( "Hello, World!\n" );
return 0;
}
Penambahan variabel __global__ pada
fungsi kernel()berfungsi untuk menunjukkan pada compiler bahwa
program tersebut dikompilasi untuk berjalan pada device dan bukan
pada host. Selanjutnya kita akan melihat contoh program lagi dimana
terdapat bagian pengiriman nilai.
#include
#include "book.h"
__global__ void add( int a, int
b, int *c ) {
*c = a + b;
}
int main( void ) {
int c;
int *dev_c;
HANDLE_ERROR( cudaMalloc(
(void**)&dev_c, sizeof(int) ) );
add<<<1>>>( 2, 7, dev_c
);
HANDLE_ERROR( cudaMemcpy( &c, dev_c,
sizeof(int), cudaMemcpyDeviceToHost )
);
printf( "2 + 7 = %d\n", c );
cudaFree( dev_c );
return 0;
}
Variabel dev_c adalah
variabel yang akan digunakan untuk menampung nilai yang akan dilewatkan
dari host ke device dan setelah itu
nilai tersebut akan diambil dari device dan dikirim ke host. Metode
pengalokasian memori memanfaatkan fungsi cudaMalloc() yang
fungsinya mirip malloc() pada C. Untuk mengambil nilai dari device memanfaakan
fungsi cudaMemcpy().
Sekarang bagaimanakah paralel
pada GPU? Kita lihat program penjumlahan vektor berikut ini.
#include
"../common/book.h"
#define N 10
__global__ void add( int *a, int
*b, int *c ) {
int tid = blockIdx.x;
// handle the data at this index
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 ) );
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
cudaFree( dev_a ); cudaFree(
dev_b ); cudaFree( dev_c ); return 0;
Program yang dapat dijadikan
paralel adalah program yang digunakan untuk menghasilkan satu nilai dimana
nilai keluarannya tersebut tidak dipengaruhi oleh nilai lain dari komputasi
dengan fungsi yang sama. Contohnya adalah dalam program penjumlahan vektor ini.
Dalam penjumlahan vektor nilai c(0)adalah penjumlahan antara a(0) dan b(0) dan
tidak dipengaruhi oleh nilai c(1), c(2), dst.
Pada program ini juga terdapat bagian
yang bertuliskan add<<<N,1>>>. Bagian ini
menunjukkan bahwa program memanfaatkan N buah thread.
Nilai N buah ini diperoleh dari :
N
buah block x 1 threadper block
Untuk menentukan jumlah thread yang
akan digunakan dapat diatur dengan mengubah kedua nilai tersebut.
Fungsi add<<<1,N>>> akan menghasilkan
penggunaan jumlah thread yang sama dengan fungsi ini add<<<N,1>>>.
Jumlahblock dan thread per block tentu saja
terbatas dan untuk setiap device akan berbeda jumlahnya. Anda
dapat melihatnya menggunakan fungsi properti dari CUDA. Program di atas
juga hanya menggunakan 1 thread pada setiap block.
Oleh karena itu identifikasi posisi cukup dengan mengambil posisi block yang
menjalankan komputasi dengan memanggil variabel blockIdx.x.
Hal lain yang akan menjadi penting dalam pemanfaatan
CUDA ada kemampuan untuk merepresentasikan array 2D atau 3D dalam array 1D. Kemampuan
ini akan mempermudah kita dalam pembuatan program untuk pengalokasian memori
serta pengaturan jumlah thread. Untuk belajar lebih jauh lagi
tentang pemrograman paralel dengan CUDA dapat mempelajari berbagai bahan untuk
belajar yang disediakan oleh NVIDIA seperti pada http://developer.nvidia.com//suggested-reading
dan http://developer.nvidia.com/cuda-training
0 komentar:
Posting Komentar