You are on page 1of 9

Metode Foster: Bubble Sort Parallel

Wayan Sriyasa/G651080154
Departemen Ilmu Komputer, FMIPA, IPB

Implementasi Bubble Sort


Dengan Metode Foster dan MPI

Pendahuluan
Pengurutan/sorting data merupakan operasi yang sangat umum dilakukan oleh
komputer karena data yang terurut lebih mudah diproses daripada data yang masih
acak. Sorting didefinisikan sebagi sebuah task untuk mengatur sekumpulan data yang
tersusun secara acak sehingga dihasilkan susunan yang terurut sesuai dengan elemen-
nya (dari yang kecil ke besar atau sebaliknya).
Mem-parallel-kan sebuah algoritma sequencial sorting melibatkan pendistribusian
elemen yang akan diurutkan kepada prosesor yang tersedia. Ada beberapa hal yang
harus diperhatikan, yaitu:
1. dimana tempat penyimpanan input dan output
o pada algoritma sekuensial proses ini dengan cepat dapat dilakukan hanya
dengan menggunakan memori lokalnya
o pada algoritma parallel, jika elemen terletak pada proses lokal maka akan
menjadi cukup mudah sedangkan jika elemen berada pada proses yang
berbeda maka akan menjadi lebih rumit
2. Bagaimana proses pembandingan dilakukan oleh algoritma
o Satu elemen per proses
o Lebih dari satu elemen per proses

Desain Parallel Dengan Metode Foster


Salah satu metode yang umum dipakai dalam mendesain algoritma parallel
adalah dengan menerapkan metode Foster. Task sebagai unit komputasi terdiri dari:
 Program
 Local Memory
 Sekumpulan I/O ports
Task pada program parallel berkomunikasi satu sama lain melalui pertukaran pesan
(message excahange).
Metode Foster pada dasarnya merupakan serangkaian tahapan mulai dari
pembagian data/proses menjadi beberapa bagian (task), menentukan komunikasi antar
task, mengumpulkan task yang memiliki komunikasi intens terhadap task yang lainnya,
dan terakhir melakukan mapping kelompok task tersebut kedalam beberapa prosesor
yang ada. Berikut detail metode Foster:
1. Partitioning
Pada tahap ini dilakukan pemecahan data maupun komputasi menjadi
bagian yang lebih kecil. Terdapat 2 jenis partitioning: Domain Decomposition dan
Functional Decomposition. Beberapa hal yang perlu diperhatikan ketika
melakukan partitioning antara lain:
 Minimasi kompustasi yang berlebihan dan storage data yang redundan.
 Task yang sudah primitif (task yang tidak terbagi lagi) berukuran sama satu
dengan yang lainnya.
 Jumlah task akan bertambah seiring dengan bertambahnya ukuran
masalah.
Metode Foster: Bubble Sort Parallel

Wayan Sriyasa/G651080154
Departemen Ilmu Komputer, FMIPA, IPB

2. Communication
Pada tahap ini ditentukan struktur komunikasi antar task yang ada.
Komunikasi ini nanti akan menentukan struktur data dan nilai yang akan
dipertukarkan diantara task. Terdapat 2 macam komunikasi:
 Komunikasi Lokal (Local Communication): task memerlukan nilai dari
sejumlah kecil task yang lainnya. Channel untuk ilustrasi aliran data perlu
dibuat.
 Komunikasi Global (Global Communication): task dalam jumlah yang
signifikan mengkontribusikan data untuk melakukan komunikasi satu sama
lain. Sangat tidak disarankan untuk membuat channel pada tahap awal
desain.
Beberapa hal yang perlu diperhatikan agar operasi komunikasi berjalan seimbang
diantara task antara lain:
 Setiap task berkomunikasi hanya dengan grup kecil saja
 Task dapat melakukan komunikasi secara concurrent
 Task dapat melakukan komputasi secara concurrent
3. Agglomeration
Pada tahap ini, beberapa task dikelompokkan menjadi bagian yang lebih
besar. Task dikelompokkan dipilih berdasarkan "kedekatannya" satu sama lain
sehingga performa dapat ditingkatkan, memelihara skalabilitas program dan
menyederhanakan pemrograman. Pada MPI, biasanya satu agglomerated task
dibuat untuk satu prosesor.
4. Mapping
Pada proses ini, agglomerated task diproses pada prosesor. Terdapat situasi
dimana mapping otomatis dilakukan oleh Operating System (Centralized
Multiprocessor), dan pada situasi lainnya mapping harus dilakukan manual
(Distributed Memory System).
Terdapat tujuan yang saling bertolak belakang ketika melakukan mapping,
dimana disatu sisi utilisasi prosesor harus dimaksimumkan sedangkan disisi lain
komunikasi interprosesor harus diminimasi. Untuk memperoleh mapping task yang
optimal merupakan sebuah kasus yang cukup rumit (NP-Hard Problem).

MPI (Message Passing Interface)


Paradigma pemrograman Message Passing merupakan salah satu paradigma
yang tertua dan telah cukup lama digunakan untuk pendekatan pemrograman parallel.
Secara umum ada dua atribut kunci dalam pemrograman message passing (MP). Atribut
pertama adalah MPI mengasumsikan address space yang terbagi dan yang kedua MP
hanya mendukung parallelisasi yang eksplisit.
Pandangan logis dari sebuah mesin yang mendukung paradigma MP terdiri dari p
proses, setiap proses memiliki address space-nya sendiri yang eksklusif. Ada dua implikasi
penting dari address space terbagi, pertama setiap elemen data harus merupakan
bagian dari address space, sehingga data dibagai dan diposisikan secara eksplisit. Hal ini
akan menambah kompleksitas program nantinya. Implikasi ke-2 adalah semua interaksi
(read-only atau read/write) membutuhkan kerjasama dari dua proses (proses yang
memiliki data dan proses yang akan mengakses data tersebut). Kebutuhan akan
kerjasama ini juga menambah kompleksitas. Dimana proses yang memiliki data harus
terlibat walaupun tidak ada hubungan logis terhadap even pada proses yang
memerlukan data.
Metode Foster: Bubble Sort Parallel

Wayan Sriyasa/G651080154
Departemen Ilmu Komputer, FMIPA, IPB

Struktur MP biasanya dibuat dengan paradigma asynchronous atau loosely


synchronous. Pada paradigma asynchronous, semua task yang concurrent dieksekusi
secara asynchronous. Hal ini memungkinkan implementasi berbagai macam algoritma
parallel. Secara umum, paradigma MP mendukung eksekusi program yang berbeda
pada setiap 'p' proses. Hampir semua program MP dibuat dengan pendekatan SPMD
(Single Program Multiple Data).
MPI (Message Passing Interface) mendefinisikan sebuah library standar untuk MPI
yang nantinya dapat digunakan untuk membangun program MP diselesaikan. Library
MPI terdiri dari 125 rutin, dan rutin standar yang biasa dipakai adalah sebagai berkut:

Fungsi Notasi Keterangan


MPI_Init int MPI_Init(int *argc, char ***argv) Inisialisasi MPI
MPI_Finalize int MPI_Finalize() Terminasi MPI
Menentukan jumlah
MPI_Comm_size int MPI_Comm_size(MPI_Comm comm, int *size)
proses
Menentukan label
MPI_Comm_rank int MPI_Comm_rank(MPI_Comm comm, int *rank)
proses
int MPI_Send(void *buf, int count, MPI_Datatype datatype,
MPI_Send int dest, int tag, MPI_Comm comm) Mengirim pesan

int MPI_Recv(void *buf, int count, MPI_Datatype datatype,


MPI_Recv int source, int tag, MPI_Comm comm, MPI_Status *status) Menerima pesan

int MPI_Barrier int MPI_Barrier(MPI_Comm comm) Sinkronisasi operasi


int MPI_Bcast(void *buf, int count, MPI_Datatype datatype, Operasi one-to-all
int MPI_Bcast int source, MPI_Comm comm) broadcast

int MPI_Reduce(void *sendbuf, void *recvbuf, int count,


Operasi one-to-all
int MPI_Reduce MPI_Datatype datatype, MPI_Op op, int target,
MPI_Comm comm) reduction

int MPI_Gather(void *sendbuf, int sendcount,


int MPI_Gather MPI_Datatype senddatatype, void *recvbuf, int recvcount, Operasi gather
MPI_Datatype recvdatatype, int target, MPI_Comm comm)

int MPI_Scatter(void *sendbuf, int sendcount,


int MPI_Scatter MPI_Datatype senddatatype, void *recvbuf, int recvcount, operasi scatter
MPI_Datatype recvdatatype, int source, MPI_Comm comm)

Bubble Sort
Algoritma bubble sort menganalogikan setiap angka sebagai sebuah gelembung.
Angka/elemen yang lebih kecil akan naik sama seperti gelembung yang selalu
mengambang ke permukaan. Berikut algoritma Bubble Sort sekuensial:

1. procedure BUBBLE_SORT(n)
2. begin
3. for i := n-1 to 0 do
4. for j := 0 to i do : k = j+1
5. if A(j)> A(k) then
6. temp = A(j)
7. A(j) = A(k)
8. A(k) = temp
9. end if
10. end BUBBLE_SORT
Metode Foster: Bubble Sort Parallel

Wayan Sriyasa/G651080154
Departemen Ilmu Komputer, FMIPA, IPB

Dalam setiap loop i algoritma akan "menggelembungkan" bilangan terkecil ke-i


hingga ke posisi ke-i didalam array. Penggelembungan dimulai dari elemen terakhir
array. Setiap pasang elemen yang berdekatan akan dibandingkan. Jika elemen yang
dibelakang lebih kecil, maka dilakukan penukaran. Dengan cara ini, bilangan terkecil
pasti akan "naik terbawa" hingga ke posisi yang sebenarnya. Iterasi pada setiap loop
terjadi sebanyak (n) kali, sehingga total waktu yang diperlukan adalah (n2).

Gambar 1. Ilustrasi Algoritma Bubble Sort

Algoritma sekuensial ini dapat di-parallelkan dengan menerapkan metode Foster. Berikut
tahap-tahap desain algoritma parallel Bubble Sort:
1. Partitioning
Dekomposisi dilakukan dengan membagi data (domain decomposition).
Pembagian data dilakukan oleh prosesor master dengan membagi jumlah data
rata kesetiap prosesor sebanyak N/P (N = jumlah data, P = jumlah prosesor).

Kemudian setiap prosesor akan melakukan pengurutan data secara sekuensial


disetiap prosesor. Berikut proses sekuensial yang terjadi disetiap prosesor:
sort (int* v, int n)
{
int i, j;

for (i = n - 2; i >= 0; i--)


for (j = 0; j <= i; j++)
if (v[j] > v[j + 1])
int t;
t = v[i];
v[i] = v[j];
v[j] = t;
}

Setelah data diurutkan disetiap prosesor, kemudian prosesor master bertugas untuk
menggabungkan hasil tersebut:
Metode Foster: Bubble Sort Parallel

Wayan Sriyasa/G651080154
Departemen Ilmu Komputer, FMIPA, IPB

int* mergeArrays (int* v1, int n1, int* v2, int n2)
{
int i, j, k;
int* result;

result = (int *)malloc ((n1 + n2) * sizeof (int)); //alokasi space


//untuk hasil array

//gabung array dan letakkan dalam urutan !


i = 0;
j = 0;
k = 0;

while (i < n1 && j < n2)


if (v1[i] < v2[j]) {
result[k] = v1[i];
i++;
k++;
} else {
result[k] = v2[j];
j++;
k++;
}

if (i == n1)
while (j < n2) {
result[k] = v2[j];
j++;
k++;
}
else
while (i < n1) {
result[k] = v1[i];
i++;
k++;
}

return result;
}

2. Communication
Komunikasi terjadi ketika data disebarkan dari prosesor master menuju prosesor
slave dan sebaliknya ketika prosesor slave mengirimkan hasil komputasi ke prosesor
master.

Pengiriman data menuju prosesor slave:

MPI_Bcast (&s, 1, MPI_INT, 0, MPI_COMM_WORLD);


resultant_array = (int *)malloc (s * sizeof (int)); //Alokasi hasil array
//Kirim data array dari Prosesor Utama (Master) ke prosesor slave
MPI_Scatter (data, s, MPI_INT, resultant_array, s, MPI_INT, 0, MPI_COMM_WORLD);
sort (resultant_array, s);
} else {
MPI_Bcast (&s, 1, MPI_INT, 0, MPI_COMM_WORLD);
//Alokasi hasil array
resultant_array = (int *)malloc (s * sizeof (int));
MPI_Scatter (data, s, MPI_INT, resultant_array, s, MPI_INT, 0, MPI_COMM_WORLD);
//Setiap slave prosesor akan menyortir berdasarkan pembagian array n/p
sort (resultant_array, s); //Sortir array hingga index s.
}
Metode Foster: Bubble Sort Parallel

Wayan Sriyasa/G651080154
Departemen Ilmu Komputer, FMIPA, IPB

Pengiriman hasil pengurutan data dari prosesor slave menuju master


while (move < p) {
if (id%(2*move)==0) {
if (id + move < p) { //Terima sub array
MPI_Recv (&m, 1, MPI_INT, id + move, 0, MPI_COMM_WORLD, &status);
sub = (int *)malloc (m * sizeof (int)); //alokasi space untuk sub array
MPI_Recv (sub, m, MPI_INT, id + move, 0, MPI_COMM_WORLD, &status);
}

3. Agglomeration
Proses agglomerasi terjadi ketika penggabungan 2 sub-array, dan
mengurutkannya kembali ke prosesor lain.
4. Mapping
Mapping dilakukan ketika data yang telah di-agglomerasi siap dikirim ke prosesor
terdekat.
int near = id - move; //mencari prosesor terdekat
MPI_Send (&s, 1, MPI_INT, near, 0, MPI_COMM_WORLD);
MPI_Send (resultant_array, s, MPI_INT, near, 0, MPI_COMM_WORLD);
break;

Berikut hasil implementasi serangkaian proses diatas.

Gambar 2. Hasil implementasi Parallel Bubble Sort dengan MPI

Kompleksitas algoritma bubble sort setelah diparallelkan adalah sebagai berikut:


 Jika p adalah jumlah prosesor, dimana p<n.
 Setiap proses diberikan blok beban sebanyak n/p, kemudian melakukan
pembandingan dan pengurutan lokal. Karena kompleksitas sort sekuensial
untuk n elemen adalah (n log n), maka kompleksitas yang terjadi disetiap
prosesor menjadi (n/p log n/p).
 Proses pembandingan memerlukan (n).
 Waktu komunikasi yang diperlukan adalah (n).
n n
Tp   log   n  n
p p

sort lokal pembandingan komunikasi

Mengingat kompleksitas pengurutan sekuensial adalah (n log n), maka speedup dan
efisiensi formulasi ini adalah
(n log n) 1
S , E
((n / p)log(n / p))  (n) 1 ((log p)/(log n))  (p / log n)
Metode Foster: Bubble Sort Parallel

Wayan Sriyasa/G651080154
Departemen Ilmu Komputer, FMIPA, IPB

Kesimpulan
Pengurutan/sorting data merupakan operasi yang sangat umum dilakukan oleh
komputer karena data yang terurut lebih mudah diproses daripada data yang masih
acak. Mem-parallel-kan sebuah algoritma sequencial sorting melibatkan pendistribusian
elemen yang akan diurutkan kepada prosesor yang tersedia.
Salah satu metode yang umum dipakai dalam mendesain algoritma parallel
adalah dengan menerapkan metode Foster. Metode Foster pada dasarnya merupakan
serangkaian tahapan mulai dari pembagian data/proses menjadi beberapa bagian
(task), menentukan komunikasi antar task, mengumpulkan task yang memiliki komunikasi
intens terhadap task yang lainnya, dan terakhir melakukan mapping kelompok task
tersebut kedalam beberapa prosesor yang ada.
Paradigma pemrograman Message Passing merupakan salah satu paradigma
yang tertua dan telah cukup lama digunakan untuk pendekatan pemrograman parallel.
Struktur MP biasanya dibuat dengan paradigma asynchronous atau loosely synchronous.
Pada paradigma asynchronous, semua task yang concurrent dieksekusi secara
asynchronous. Secara umum, paradigma MP mendukung eksekusi program yang
berbeda pada setiap 'p' proses. Hampir semua program MP dibuat dengan pendekatan
SPMD (Single Program Multiple Data).
Algoritma bubble sort menganalogikan setiap angka sebagai sebuah gelembung.
Angka/elemen yang lebih kecil akan naik sama seperti gelembung yang selalu
mengambang ke permukaan. Waktu yang diperlukan oleh algoritma bubblesort
sekuensial adalah (n2) dan untuk algoritma bubblesort parallel menjadi
n n
Tp   log    n  n .
p p

Referensi
Grama, A; Gupta, A; Karypis, George; dan Kumar, V. 2003. Introduction to Parallel
Computing, Second Edition – Chapter 6 Programming Using the Message-
Passing Paradigm. Addison Wesley. USA
Quinn, M.J. 2004. Parallel Programming in C with MPI and OpenMP. McGrawHill. USA.
Metode Foster: Bubble Sort Parallel

Wayan Sriyasa/G651080154
Departemen Ilmu Komputer, FMIPA, IPB

Listing kode:
=======================================================
/*
PARALLEL BUBLE SORT
#include <stdio.h>
#include <mpi.h>

int* mergeArrays (int* v1, int n1, int* v2, int n2)
{
int i, j, k;
int* result;
result = (int *)malloc ((n1 + n2) * sizeof (int)); //alokasi space
//gabung array dan letakkan dalam urutan !
i = 0;
j = 0;
k = 0;
while (i < n1 && j < n2)
if (v1[i] < v2[j]) {
result[k] = v1[i];
i++;
k++;
} else {
result[k] = v2[j];
j++;
k++;
}

if (i == n1)
while (j < n2) {
result[k] = v2[j];
j++;
k++;
}
else
while (i < n1) {
result[k] = v1[i];
i++;
k++;
}

return result;
}

sort (int* v, int n)


{
int i, j;
int t;
for (i = n - 2; i >= 0; i--)
for (j = 0; j <= i; j++)
if (v[j] > v[j + 1])
t = v[i];
v[i] = v[j];
v[j] = t;
}

main (int argc, char ** argv)


{
FILE* fin; //Input File, (unsorted Array)

int* data; //unsorted array


int* resultant_array; //Sorted Array
int* sub;
//Variables Penting
int m, n;
int id, p;
int s;
int i;
int z;
int move;
MPI_Status status;
MPI_Init (&argc, &argv);
MPI_Comm_rank (MPI_COMM_WORLD, &id);
MPI_Comm_size (MPI_COMM_WORLD, &p);
Metode Foster: Bubble Sort Parallel

Wayan Sriyasa/G651080154
Departemen Ilmu Komputer, FMIPA, IPB

//Task untuk Processor Utama


if (id == 0) {
//Baca data dari file dan prosedur inisialisasi lain.
int r;
fin = fopen ("data.txt", "r"); //Open file .
fscanf (fin, "%d", &n);
s = n / p;
r = n % p;
data = (int *)malloc ((n + s - r) * sizeof (int));

for (i = 0; i < n; i++)


fscanf (fin, "%d", &(data[i])); //Baca data dari file.

fclose (fin); //Tutup file.

if (r != 0) {
for (i = n; i < n + s - r; i++)
data[i] = 0;

s = s + 1;
}
MPI_Bcast (&s, 1, MPI_INT, 0, MPI_COMM_WORLD);
resultant_array = (int *)malloc (s * sizeof (int)); //Alokasi hasil array
//Kirim data array dari Prosesor Utama (Master) ke prosesor slave
MPI_Scatter (data, s, MPI_INT, resultant_array, s, MPI_INT, 0, MPI_COMM_WORLD);
sort (resultant_array, s);
} else {
MPI_Bcast (&s, 1, MPI_INT, 0, MPI_COMM_WORLD);
//Alokasi hasil array
resultant_array = (int *)malloc (s * sizeof (int));
MPI_Scatter (data, s, MPI_INT, resultant_array, s, MPI_INT, 0, MPI_COMM_WORLD);
//Setiap slave prosesor akan menyortir berdasarkan pembagian array n/p
sort (resultant_array, s); //Sortir array hingga index s.
}
move = 1;
//Gabung sub sortir array untuk menghasilkan resultan array yg sudh di sortir
while (move < p) {
if (id%(2*move)==0) {
if (id + move < p) { //Terima sub array
MPI_Recv (&m, 1, MPI_INT, id + move, 0, MPI_COMM_WORLD, &status);
sub = (int *)malloc (m * sizeof (int)); //alokasi space untuk sub array
MPI_Recv (sub, m, MPI_INT, id + move, 0, MPI_COMM_WORLD, &status);
//menghasilkan resultant array dengan menggabung sub sortir array
resultant_array = mergeArrays (resultant_array, s, sub, m);
s = s + m;
}
} else { //Kirim data ke prosesor yang lain
int near = id - move;
MPI_Send (&s, 1, MPI_INT, near, 0, MPI_COMM_WORLD);
MPI_Send (resultant_array, s, MPI_INT, near, 0, MPI_COMM_WORLD);
break;
}
move = move * 2;
}
//Tahapan Final, Master CPU memberikan hasil.!!!
if (id == 0) {
//Hasilkan ukuran Array, Processors Yang Digunakan, Total Waktu Kerja
printf ("\nUkuran Array: %d \nTotal processor(s): %d \n",s, p);
}
MPI_Finalize (); //Finalisasi MPI.
//Hasilkan Unsorted array dan Yang telah di sortir.
printf ("\nArray Sebelum Di Sortir:\n\n");
for (z = 0; z < s; ++z)
printf ("%d ", data[z]);
printf ("\n\nArray Yang Telah Di Sortir:\n\n");
for (z = 0; z < s; ++z)
printf ("%d ", resultant_array[z]);
printf ("\n");
}

You might also like