laporan grid ncc 1
TRANSCRIPT
LAPORAN
KOMPUTASI GRID
Cluster 1 NCC
Kelompok Cluster NCC 1 :Rizky Septiandy W. Adhitya Bhawiyuga PujiantoYogie SetiarkoDhanang Cindra
DosenF.X. Arunanto
JURUSAN TEKNIK INFORMATIKAFAKULTAS TEKNOLOGI INFORMASI
INSTITUT TEKNOLOGI SEPULUH NOPEMBER
2010
Konfigurasi Cluster II Grid
Laboratorium Net Centric Computing
Topologi Jaringan
Topologi jaringan secara keseluruhan adalah :
Topologi pada cluster NCC adalah :
Rancangan Software
Untuk pengenmbangan sistem grid ini, dibutuhkan beberapa perangkat lunak. Perangkat lunak tersebut hampir kesemuanya bersifat gratis dan open source. Berikut kebutuhan perangkat lunak untuk sistem grid.
1. Sun Grid Engine Mengatur penjadwalan dan melakukan machines serta menjalankan perintah- perintah dalam unix.
2. Globus Toolkit
Gambar 1: Topologi Cluster ITS
Gambar 2 : Topologi Cluster NCC
Management Tools yang merupakan middleware antara antarmuka web dengan scheduler.
3. GridSphereAntarmuka web sebagai media user untuk mengirimkan job ke cluster grid.
4. MPICH Aplikasi untuk mengkompile dan menjalankan aplikasi berbasis MPI.
5. JD2SDK 1.5 +Framework java yang dipakai untuk menjalankan aplikasi berbasis java.
* sampai laporan dibuat, yang bertanda bintang sudah diinstall dan dikonfigurasi
Konfigurasi MPICH
Requirement
Sebuah alamat IP statis maupun dinamis (statis lebih disarankan). Pada kasus ini akan dibangun 3 buah node dalam satu cluster dengan nama dan IP sebagai berikut:
1. ncca1 dengan alamat 10.151.32.5 sebagai master2. ncca2 dengan alamat 10.151.32.26 sebagai slave3. ncca3 dengan alamat 10.151.32.23 sebagai slave
Setting IP
Untuk mensetting IP, kita edit file /etc/networking/interfaces pada tiap-tiap node di atas. Konfigurasi di tiap node adalah :
1. Pada ncca1 auto lo iface lo inet loopback auto eth0 iface eth0 inet static address 10.151.32.5 netmask 255.255.255.0 broadcast 10.151.32.255 gateway 10.151.32.1
2. Pada ncca2 auto lo iface lo inet loopback auto eth0 iface eth0 inet static address 10.151.32.26 netmask 255.255.255.0 broadcast 10.151.32.255
gateway 10.151.32.13. Pada ncca3
auto lo iface lo inet loopback auto eth0 iface eth0 inet static address 10.151.32.23 netmask 255.255.255.0 broadcast 10.151.32.255 gateway 10.151.32.1 Kemudian restart interface dengan printah /etc/init.d/networking restart.
Konfigurasi Hosts
Kita perlu memberikan nama domain untuk setiap node yang ada pada cluster. Kita dapat mengedit file /etc/hosts pada setiap node dengan nama dan IP semua node yang terlibat dalam cluster ini. Konfigurasi dalam setiap host harus sama untuk menghindari error seperti mpdboot_server (handle_mpd_output 407): failed to handshake with mpd on 10.0.0.2; recvd
output={}
Pada setiap node : 127.0.0.1 localhost 10.151.32.5 ncca1 10.151.32.26 ncca2 10.151.32.23 ncca3
Kebutuhan Paket
• libmpich1.0-dev - mpich static libraries dan development files
• libmpich-mpd1.0-dev - mpich static libraries dan development files
• libmpich-shmem1.0-dev - mpich static libraries dan development files
• mpich2 - Implementasi standar MPI Message Passing Interface.• mpich2-doc - Dokumentasi MPICH2
• openssh-server - secure shell (SSH) server• build-essentials - paket build-essential.
Lakukan proses instalasi pada setiap node di cluster dengan perintah :
grid@ncca1:~$ sudo apt-get install libmpich1.0-dev libmpich-mpd1.0-dev libmpich-shmem1.0-dev mpich2 mpich2-doc john openssh-server build-essentials
Konfigurasi User
Dalam cluster yang akan kita bangun, kita akan menggunakan user dengan nama yang sama pada setiap node. Dengan alasan keamanan, kita tidak akan menggunakan user root. Oleh karena itu, kita membuat user baru yaitu user grid pada setiap node dengan perintah:
grid@ncca1:~$ sudo useradd gridgrid@ncca1:~$ sudo passwd cluster
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
Membuat NFS Server dan Client
NFS Server adalah sistem yang digunakan node-node dalam cluster ini berbagi resource file yang akan dikerjakan. Master akan menjadi NFS Server dimana nantinya suatu bagian dari filesystem pada node master akan dapat dimount oleh node slave sebagai NFS Client dan akhirnya master dan slave akan berbagi file yang akan dikerjakan oleh cluster tersebut. Setting pada setiap node adalah :
1. Master (ncca1) grid@ncca1:~$ sudo mkdir /mirror grid@ncca1:~$ chmod 777 /mirror grid@ncca1:~$ sudo apt-get install nfs-kernel-server grid@ncca1:~$ sudo echo /mirror *(rw,sync) >> /etc/exports
2. Slave (ncca2) grid@ncca2:~$ sudo mkdir /mirror grid@ncca2:~$ sudo chmod 777 /mirror grid@ncca2:~$ sudo apt-get install nfs-common grid@ncca2:~$ sudo mount ncca1:/mirror /mirror
3. Slave (ncca3) grid@ncca3:~$ sudo mkdir /mirror grid@ncca3:~$ sudo chmod 777 /mirror grid@ncca2:~$ sudo apt-get install nfs-common grid@ncca2:~$ sudo mount ncca1:/mirror /mirror
Konfigurasi SSH
Untuk berkomunikasi antar node dibutuhkan akses ssh pada user grid tanpa password. Untuk itu, pada setiap node harus saling disetting dengan node yang lain, dan sifatnya bolak-balik. Contoh, misal antara node ncca1 dan node ncca2.
Pada node ncca1 (master)grid@ncca1:~$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/grid/.ssh/id_rsa):
Created directory '/home/grid/.ssh'
Enter passpharse (empty for no passpharse):
Enter same passpharse again:
Your identification has been saved in /home/grid/.ssh/id_rsa.
Your public key has been saved in /home/grid/.ssh/id_rsa.pub.
The key fingerprint is:
0f:d7:c4:14:cf:06:11:d5:80:ec:1f:c3:f3:3b:7f:22 grid@ncca1The key's randomart image is:
[picture omitted]
grid@ncca1:~$ cat /home/grid/.ssh/id_rsa.pub | ssh grid@ncca2 'cat >> /home/grid/.ssh/authorized_keys'
Kosongkan passphrase yang diminta saat ssh-keygen, langsung tekan enter. Setelah langkah diatas maka sistem akan dapat melakukan SSH tanpa password, lakukan hal yang sama pada slave slave lain dengan target host SSH diganti dengan ncca1.
Konfigurasi MPICH
Pada setiap node, buat file konfigurasi untuk mpich sebagai berikut :• File ~/.mpd.conf
File ini berisi konfigurasi secretword yang harus sama pada setiap node. Gunanya agar setiap node dapat berinteraksi dengan aman. Misal kita isi dengan secretword=grid. File ini harus memiliki permission 600 agar hanya dapat dibaca dan ditulis oleh user grid.
• File ~/mpd.hostsFile ini berisi nama host setiap node yang terlibat dalam cluster. Misal isi dari file tersebut.ncca1ncca2ncca3
Menjalankan Mesin
Untuk menjalankan mesin pada semua grid, dapat dilakukan dengan beberapa perintah yaitu :
• mpdboot – start the cluster
• mpdtrace - list all nodes in the cluster
• mpdallexit – shut down the cluster
Pada kasus ini, kita akan menjalankan mesin pada semua node, yaitu dengan perintah :grid@ncca1:~$ mpdboot -n 3
Kompilasi Source Code
Misal kita mempunyai code matrix.c yang terdapat di direktori ~/matrix.c, untuk melakukan kompilasi dan menjalankan code tersebut, dilakukan dengan perintah :
grid@ncca1:~$ mpic++ matrix.c -o /mirror/matrixgrid@ncca1:~$ mpiexec /mirror/matrix
Konfigurasi Sun Grid Engine
Konfigurasi pada Head Node / Master
1. Download paket-paket berikut dari situs http://gridengine.sunsource.net/downloads/61/download.html• ge-6.1u6-common.tar.gzPaket common Sun Grid Engine untuk semua platform• ge-6.1u6-bin-lx24-x86.tar.gzPaket Sun Grid Engine untuk Linux x86
2. Buat folder pada folder yang dapat di akses oleh semua node dalam satu cluster. Dalam konfigurasi ini, folder tersebut terletak di /mirror.mkdir /mirror/ge-common
3. Ekstrak dua file yang telah diunduh di atas dalam folder /mirror/ge-common dengan perintah.tar -xvzf ge-6.1u6-common.tar.gztar -xvzf ge-6.1u6-bin-lx24-x86.tar.gz
4. Setting path SGE_ROOT dengan lokasi kita mengekstrak dua file di atas yaitu di folder /mirror/ge-commonexport SGE_ROOT=/mirror/ge-common
5. Jalankan file instalasi dengan perintah./install_qmasterPada saat inistalasi akan diajukan beberapa pertanyaan. Pertanyaan tersebut dapat dijawab sesuai dengan konfigurasi dari node yang kita punya.
6. Untuk mengecek host yang terdaftar dalam lingkungan SGE, dapat dilakukan dengan perintah /bin/lx24-x86/qconf -sh
7. Jika host yang terdaftar masih kosong, dpaat ditambah dengan perintah /bin/lx24-x86/qconf -ah. Pada kasus cluster ini terdapat 3 host yaitu ncca1, ncca2, dan ncca3./bin/lx24-x86/qconf -ah ncca1/bin/lx24-x86/qconf -ah ncca2/bin/lx24-x86/qconf -ah ncca3
8. Konfigurasi SGE agar dapat mengenali MPICH yang sudah terlebih dahulu terinstall. Perintahyang dijalankan adalah
/bin/lx24-x86/qconf -ap mpich9. Setelah menjalankan perintah tersebut, akan muncul setting konfigurasi. Isikan setting
konfigurasi seperti berikutpe_name mpich slots 9999 user_lists NONE xuser_lists NONE start_proc_args /mirror/ge-common/mpi/startmpi.sh $pe_hostfile stop_proc_args /mirror/ge-common/mpi/stopmpi.sh allocation_rule $round_robin control_slaves FALSE job_is_first_task TRUE urgency_slots min pe_list make mpich
10. Simpan konfigurasi tersebut (konfigurasi tersebut diedit dengan editor default sistem anda, contoh vim).
Konfigurasi pada Worker Node / Slave
1. Pada tiap-tiap worker node / slave yang berada dalam cluster dan dapat mengakses NFS yang sudah kita buat sebelumnya, dilakukan instalasi daemon dengan perintah/mirror/ge-common/install_execdPada saat instalasi daemon akan ditanyakan beberapa pertanyaan yang harus dijawab sesuai dengan spesifikasi sistem.
Kode Pararel Programming
Matrix Vector Multiplication
Algoritma for i = 1 to n do Si : yi = 0; for j = 1 to n do yi = yi + ai,j * xj ; EndforEndfor
Pembagian proses komputasi dilakukan pada tiap row pada matrix, dimana proses komputasi hasil perkalian perbaris dibagi berdasarkan jumlah rank atau resource processor yang dijalankan
Source Code#include <stdio.h>#include <stdlib.h>#include <math.h>#include <time.h>#include "mpi.h"#define X 5#define Y 5#define Z 5#define ROW_MES_TAG 123#define MAT2_MES_TAG 1#define MAX_VALUE 10
int matrix1[X][Y];int matrix2[Y][Z];int result[X][Z];int therow[Y];int tmprow[Y];
//membuat matrix secara randomvoid generateRandomMatrix(){
int i,j;for(i=0;i<X;i++){
for(j=0;j<Y;j++)matrix1[i][j] = rand()%MAX_VALUE;
}
for(i=0;i<Y;i++){
for(j=0;j<Z;j++)matrix2[i][j] = rand()%MAX_VALUE;
}}//simpan ke temporaryvoid transfer(int rownum){
for(int i = 0; i < Y; i++){
tmprow[i] = matrix1[rownum][i];}
}
//mapping processorint proc_map(int rowNum, int size){ if((rowNum+1)%size==0) return size; else return (rowNum+1)%size;}
//komputasi satu barisvoid computeSingleRow(){
int i,j;for(j=0;j<Z;j++){
result[0][j] = 0;for(i=0;i<Y;i++){
result[0][j]+=therow[i]*matrix2[i][j];}
}}
int taskNumber(int therank, int size){
int hasil = floor(X/(size-1));if(therank<=X%(size-1)) hasil+=1;return hasil;
}
//cetak inputvoid writeMatrixInput(){
int i,j;printf("Matriks A\n====================\n");for(i=0;i<X;i++){
for(j=0;j<Y;j++){
printf("%d ",matrix1[i][j]);}printf("\n");
}printf("\nMatriks B\n====================\n");for(i=0;i<X;i++)
{ for(j=0;j<Y;j++) { printf("%d ",matrix2[i][j]); } printf("\n"); }
}
//cetakoutputvoid writeMatrixOutput(){
int i,j; printf("\n\n===HASIL PERKALIAN MATRIKS DAN MATRIKS===\n"); for(i=0;i<X;i++) { for(j=0;j<Z;j++)
{ printf("%d\t",result[i][j]); } printf("\n"); }}
bool adaSisa(int size, int CurrentRow){
if(X%(size-1)!=0 && CurrentRow==X-1)return true;
return false;}
int main (int argc, char **argv){
srand ( time(NULL) );
int rank; int size; int i,j,k; double time0, time1;
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size); MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if(rank==0){
generateRandomMatrix();writeMatrixInput();time0 = MPI_Wtime();for(i=1;i<size;i++)
MPI_Send(matrix2,Y*Z,MPI_INT,i,MAT2_MES_TAG,MPI_COMM_WORLD);k=0;for(i=0;i<X;i++){
transfer(i);MPI_Send(tmprow,Y,MPI_INT,proc_map(i,size-
1),ROW_MES_TAG,MPI_COMM_WORLD);//printf("\ni-nya>> %d", i);if((i+1)%(size-1)==0){
//printf("\nmasuk sini ketika i>> %d",i);for(j=1;j<=(size-1);j++){
MPI_Recv(result[k],Z,MPI_INT,j,ROW_MES_TAG,MPI_COMM_WORLD,&status);k+=1;
}}
if(adaSisa(size,i)){
for(j=1;j<=X%(size-1);j++) { MPI_Recv(result[k],Z,MPI_INT,j,ROW_MES_TAG,MPI_COMM_WORLD,&status); k+=1; }
}
} time1 = MPI_Wtime(); printf ("\nWaktu Total (Komputasi+Pengiriman) : [%f] seconds\n", time1 - time0);
writeMatrixOutput();}
if(rank!=0){
MPI_Recv(matrix2,Y*Z,MPI_INT,0,MAT2_MES_TAG,MPI_COMM_WORLD,&status);int flag = taskNumber(rank,size);//printf("\nflag = %d",flag);for(int i=0;i < flag;i++){
MPI_Recv(therow,Y,MPI_INT,0,ROW_MES_TAG,MPI_COMM_WORLD,&status);time0 = MPI_Wtime();
computeSingleRow();time1 = MPI_Wtime();
printf ("\nWaktu Komputasi ke-%d : [%f] seconds\n",i, time1 - time0);
MPI_Send(result[0],Z,MPI_INT,0,ROW_MES_TAG,MPI_COMM_WORLD);}
}
MPI_Finalize();
return 0;}
Dokumentasi
Matrix Matrix Multiplication
Algoritmafor i = 1 to n do Ti : for j = 1 to n do sum = 0; for k = 1 to n do sum = sum + a(i,k) * b (k,j); Endfor c(i,j) = sum; EndforEndfor
Source Code#include <stdio.h>#include <stdlib.h>#include <math.h>#include <time.h>
#include "mpi.h"#define X 5#define Y 5#define Z 5#define ROW_MES_TAG 123#define MAT2_MES_TAG 1#define MAX_VALUE 10
int matrix1[X][Y];int matrix2[Y][Z];int result[X][Z];int therow[Y];int tmprow[Y];
//membuat matrix secara randomvoid generateRandomMatrix(){
int i,j;for(i=0;i<X;i++){
for(j=0;j<Y;j++)matrix1[i][j] = rand()%MAX_VALUE;
}
for(i=0;i<Y;i++){
for(j=0;j<Z;j++)matrix2[i][j] = rand()%MAX_VALUE;
}}//simpan ke temporaryvoid transfer(int rownum){
for(int i = 0; i < Y; i++){
tmprow[i] = matrix1[rownum][i];}
}
//mapping processorint proc_map(int rowNum, int size){ if((rowNum+1)%size==0) return size; else return (rowNum+1)%size;}
//komputasi satu barisvoid computeSingleRow(){
int i,j;for(j=0;j<Z;j++){
result[0][j] = 0;for(i=0;i<Y;i++){
result[0][j]+=therow[i]*matrix2[i][j];}
}}
int taskNumber(int therank, int size){
int hasil = floor(X/(size-1));if(therank<=X%(size-1)) hasil+=1;return hasil;
}
//cetak inputvoid writeMatrixInput(){
int i,j;printf("Matriks A\n====================\n");for(i=0;i<X;i++){
for(j=0;j<Y;j++){
printf("%d ",matrix1[i][j]);}printf("\n");
}printf("\nMatriks B\n====================\n");for(i=0;i<X;i++)
{ for(j=0;j<Y;j++) { printf("%d ",matrix2[i][j]); } printf("\n"); }
}
//cetakoutputvoid writeMatrixOutput(){
int i,j; printf("\n\n===HASIL PERKALIAN MATRIKS DAN MATRIKS===\n"); for(i=0;i<X;i++) { for(j=0;j<Z;j++) { printf("%d\t",result[i][j]); } printf("\n"); }}
bool adaSisa(int size, int CurrentRow){
if(X%(size-1)!=0 && CurrentRow==X-1)return true;
return false;}
int main (int argc, char **argv){
srand ( time(NULL) );
int rank; int size; int i,j,k; double time0, time1;
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size); MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if(rank==0){
generateRandomMatrix();writeMatrixInput();time0 = MPI_Wtime();for(i=1;i<size;i++)
MPI_Send(matrix2,Y*Z,MPI_INT,i,MAT2_MES_TAG,MPI_COMM_WORLD);k=0;for(i=0;i<X;i++){
transfer(i);MPI_Send(tmprow,Y,MPI_INT,proc_map(i,size-
1),ROW_MES_TAG,MPI_COMM_WORLD);//printf("\ni-nya>> %d", i);if((i+1)%(size-1)==0){
//printf("\nmasuk sini ketika i>> %d",i);for(j=1;j<=(size-1);j++){
MPI_Recv(result[k],Z,MPI_INT,j,ROW_MES_TAG,MPI_COMM_WORLD,&status);k+=1;
}}
if(adaSisa(size,i)){
for(j=1;j<=X%(size-1);j++) { MPI_Recv(result[k],Z,MPI_INT,j,ROW_MES_TAG,MPI_COMM_WORLD,&status); k+=1; }
}}
time1 = MPI_Wtime(); printf ("\nWaktu Total (Komputasi+Pengiriman) : [%f] seconds\n", time1 - time0);
writeMatrixOutput();}
if(rank!=0){
MPI_Recv(matrix2,Y*Z,MPI_INT,0,MAT2_MES_TAG,MPI_COMM_WORLD,&status);int flag = taskNumber(rank,size);//printf("\nflag = %d",flag);for(int i=0;i < flag;i++){
MPI_Recv(therow,Y,MPI_INT,0,ROW_MES_TAG,MPI_COMM_WORLD,&status);time0 = MPI_Wtime();
computeSingleRow();time1 = MPI_Wtime();
printf ("\nWaktu Komputasi ke-%d : [%f] seconds\n",i, time1 - time0);
MPI_Send(result[0],Z,MPI_INT,0,ROW_MES_TAG,MPI_COMM_WORLD);}
}
MPI_Finalize();
return 0;}
Dokumentasi
LAPORAN METODE GAUSS
Penjelasan Source Code :
Pertama kita menginputkan jumlah persamaan di proses master dan membroadcastnyaif (pid == 0) { printf("Enter size of matrix: "); scanf("%d",jumlahPersamaan); } MPI_Bcast(jumlahPersamaan, 1, MPI_INT, 0, MPI_COMM_WORLD);
Kemudian kita menginputkan matrix yang merupakan koefisien-koefisien persamaan linear.void inputMatrix(int n, int jumlahProsesor, float var[]){ float input[UKURAN*(UKURAN+1)], cyclic[UKURAN*(UKURAN+1)]; int i,j,count,no_rows; int sizes[jumlahProsesor], displs[jumlahProsesor];
if (pid == 0) { count = 0; printf("Enter the elements of the matrix.\n"); printf("All floats please.\n"); for (i=1; i<=n; i++)
{ for (j=1;j<=n; j++) { printf("Enter a[%d][%d]: ", i, j); scanf("%f", &input[count]); count++; } count++;}
for (i=1; i<=n; i++){ printf("Enter b[%d]: ", i); scanf("%f", &input[i*n+i-1]); }
buatCyclicMatrix(input, cyclic); }
for (i=0;i<n%jumlahProsesor;i++) sizes[i] = (n/jumlahProsesor + 1)*(n+1); for (i=n%jumlahProsesor;i<jumlahProsesor;i++) sizes[i] = (n/jumlahProsesor)*(n+1);
displs[0] = 0; for (i=1;i<jumlahProsesor;i++) displs[i] = displs[i-1] + sizes[i-1];
MPI_Scatterv(cyclic, sizes, displs, MPI_FLOAT, var, UKURAN*UKURAN, MPI_FLOAT, 0, MPI_COMM_WORLD);}
Kemudian tahap selanjutnya kita melakukan eliminasi Gauss atau yang dinamakan Forward Elimination. Di dalam fungsi eliminasi Gauss ini juga dipanggil fungsi pipeline untuk Backward Substitution nya.void eliminasiGauss(float m[], float x[]){ int j;
for (j=1; j<jumlahPersamaan; j++) dealBarisKeJ(m, j);
pipeline(pecahkanPersamaanKeI_init, pecahkanPersamaanKeI_g, pecahkanPersamaanKeI_h, m, x);}void pipeline (void (*init) (float *, float *),void (*g) (int, float *, float *, float),void (*h) (int, float *, float *),float local_vals[], float res[]){ float tmp, sum; int startelt, endelt, no_seen, no_to_receive; float accum[jumlahPersamaan]; MPI_Status status; int n = jumlahPersamaan; int x, i, j;
if (pid==(n-1)%jumlahProsesor) { (*init)(&sum, &local_vals[((n-1)/jumlahProsesor)*(n+1)]); (*h)(n-1, &sum, &local_vals[((n-1)/jumlahProsesor)*(n+1)]); res[(n-1)/jumlahProsesor] = sum; MPI_Send(&sum, 1, MPI_FLOAT, mod(pid-1,jumlahProsesor), 0, MPI_COMM_WORLD); accum[0] = sum; no_seen = 1; } else no_seen = 0;
if (n<jumlahProsesor) { if (pid < n-1) startelt = 0; else startelt = -1; } else if (n%jumlahProsesor == 0) {
if (pid < (n-1)%jumlahProsesor)startelt = n/jumlahProsesor - 1;
elsestartelt = n/jumlahProsesor - 2;
} else if (pid > n%jumlahProsesor - 2) startelt = n/jumlahProsesor - 1; else startelt = n/jumlahProsesor;
if (pid>0) endelt = 0; else endelt = 1;
for (x=startelt; x>=endelt; x--) { (*init)(&sum, &local_vals[x*(n+1)]);
for (i=0; i<no_seen; i++) (*g)(i+1, &sum, &local_vals[x*(n+1)], accum[i]);
if (no_seen==0) no_to_receive = (n-pid-1)%jumlahProsesor; else no_to_receive = jumlahProsesor-1;
for (j=0; j<no_to_receive; j++) { MPI_Recv(&tmp, 1, MPI_FLOAT, (pid+1)%jumlahProsesor, 0, MPI_COMM_WORLD, &status);
if ((j==0) && ((no_seen>0)||((no_seen==0)&&(pid==n%jumlahProsesor)))) ; else MPI_Send (&tmp, 1, MPI_FLOAT, mod(pid-1,jumlahProsesor), 0,
MPI_COMM_WORLD);
no_seen++; accum[no_seen-1] = tmp; (*g)(no_seen, &sum, &local_vals[x*(n+1)], tmp); }
(*h)(pid+jumlahProsesor*x, &sum, &local_vals[x*(n+1)]); res[x] = sum; MPI_Send(&sum, 1, MPI_FLOAT, mod(pid-1,jumlahProsesor), 0, MPI_COMM_WORLD);
no_seen++; accum[no_seen-1] = sum; }
if (pid==0)
{ (*init)(&sum, &local_vals[0]);
for (i=0; i<no_seen; i++)(*g)(i+1, &sum, &local_vals[0], accum[i]);
if (no_seen==0) no_to_receive = (n-pid-1)%jumlahProsesor; else no_to_receive = jumlahProsesor-1;
for (j=0; j<no_to_receive; j++) { MPI_Recv(&tmp, 1, MPI_FLOAT, 1, 0, MPI_COMM_WORLD, &status); no_seen++; (*g)(no_seen, &sum, &local_vals[0], tmp); }
(*h)(0, &sum, &local_vals[0]); res[0] = sum; }}Contoh :
Setelah tahap Forward Elimination menjadi
Dan setelah dilakukan Backward Substitution menjadi