Setup Parallel Programming Menggunakan MPI + Network File System

Jadi tujuan utama dari tulisan ini adalah agar pembacanya bisa dengan cepat memulai (getting started) melakukan pemrograman parallel multi komputer pada jaringan LAN yang sama. Tulisan ini juga sebagai pengingat diri saya sendiri kalau-kalau sudah lama tidak menyentuh ini dan tiba-tiba harus berurusan lagi dengan ini.

Sebelum lanjut ke tutorial sebenarnya, kita bahas teorinya dulu. Jadi dalam pemrograman parallel multi komputer terdapat 2 peran, yaitu: Head Node dan Slave Node. Head Node adalah komputer yang kita gunakan untuk memprogram semunya. Head Node bertugas mengoordinir semua Slave Node untuk membagi kerjaan yang harus di lakukan. Tentunya jika ingin berkoordinasi, berarti Head Node dan Slave Node harus bisa saling berkomunikasi. Ini artinya harus ada platform yang mengurus komunikasi ini. Inilah Peran MPI (Message Passing Interface) sebagai platform pertukaran pesan antara Head Node dan Slave Node.

Selain harus bisa saling berkomunikasi, Head Node dan Slave Node harus mempunyai storage yang bisa di akses bersama. Antara Head Node dan Slave Node sebelumnya harus terkoneksi dalam suatu jaringan yang pada umumnya adalah jaringan LAN. Inilah peran NFS (Network File Sharing) yang akan menyulap 1 direktori dari Head Node untuk bisa di akses bersama-sama oleh Head Node dan Slave Node.

Komunikasi yang digunakan oleh MPI memanfaatkan SSH. Dari Head Node akan menghubungi semua Slave Node secara serentak melalui SSH. Untuk memudahkan komunikasi yang dilakukan, akses SSH dari Head Node ke semua Slave Node hendaknya di set tanpa password.

Setelah semua itu, source code yang dicompile tentunya harus spesial. Source code yang digunakan harus mengatur tentang pembagian tugas antara Head Node dan Slave Node dan ini semua memungkinkan dengan adanya MPI.

Itu tadi pembahasan tentang cara kerja parallel programming yang akan dijelaskan setupnya di sini. Untuk perangkat kerasnya, yang kita butuhkan adalah:
- Komputer (lebih dari 1) sudah terinstall linux, rekomendasi saya ubuntu. Pada Tutorial ini komputer yang digunakan ada 4.
- Jaringan LAN yang mengoneksikan seluruh komputer tadi
Jaringan LAN yang kita gunakan pada tutorial ini adalah 192.168.1.0/24 dimana IP Head Node adalah 192.168.1.1 dan Slave Node adalah 192.168.1.2 192.168.1.3 dan 192.168.1.4.

Kalau semua itu sudah tersedia, mari kita mulai tutorialnya:

1.) Buat user yang sama pada Head Node dan Slave Node

Ini diperlukan karena MPI mengakses seluruh Head Node dan Slave Node menggunakan akun user yang sama. Pada contoh kasus ini, user untuk Head Node dan Slave Node yang akan kita gunakan adalah latprog. Untuk membuat user latprog dan sekalogus memberikannya kemampuan sudo, pada ubuntu bisa dengan
sudo adduser latprog
usermod -aG sudo latprog
view raw gistfile1.txt hosted with ❤ by GitHub

Lakukan ini pada seluruh komputer Head Node dan Slave Node

2.) Setting NFS, Seluruh Slave Node Mount direktori storage Head Node yang telah ditentukan

Ini adalah bagian yang paling sulit sebenarnya. Error yang tidak terduga selalu terjadi karena kesalahan dibagian ini. Pertama, pada seluruh Head Node dan Slave Node, buat direktori baru yang akan di mount bersama yaitu /home/latprog/nfsprog. Pada Head Node install NFS untuk server yaitu dengan perintah
sudo apt install nfs-kernel-server
view raw gistfile1.txt hosted with ❤ by GitHub
Lalu pada Slave Node, install NFS untuk client, yaitu dengan perintah
sudo apt install nfs-common
view raw gistfile1.txt hosted with ❤ by GitHub

Pada Head Node, ubah owner dan grup owner direktori /home/latprog/nfsprog menggunakan chown menjadi nobody (owner) dan nogroup (grup owner). Ini dilakukan karena untuk setiap peritah super user Slave Node pada direktori yang dimount (/home/latprog/nfsprog) oleh Head Node di anggap berasal dari user nobody pada grup nogroup (ingat, pemilik sebenarnya direktori tersebut adalah Head Node) sehingga perintah sudo dari Slave Node bisa terlaksana.
sudo chown nobody:nogroup /home/latprog/nfsprog
view raw gistfile1.txt hosted with ❤ by GitHub
Setelah itu, Head Node mendaftarkan direktori /home/latprog/nfsprog miliknya ke NFS dengan menulisnya di /etc/exports.
sudo nano /etc/exports
#isi /etc/exports, ketik seperti dibawah ini
/home/latprog/nfsprog 192.168.1.0/24(rw,sync,no_root_squash,no_subtree_check)
view raw gistfile1.txt hosted with ❤ by GitHub

Setelah itu restart NFS pada Head Node
sudo systemctl restart nfs-kernel-server
view raw gistfile1.txt hosted with ❤ by GitHub
Agar direktori Head Node bisa di mount secara LAN oleh Slave Node baik itu sekarang maupun ketika komputer dinyalakan kembali, daftarkan direktori /home/latprog/nfsprog pada /etc/fstab pada setiap Slave Node.
192.168.1.1:/home/latprog/nfsprog /home/latprog/nfsprog nfs auto,tcp,rw,intr 0 0
view raw gistfile1.txt hosted with ❤ by GitHub
Setelah itu, mount direktori tersebut dengan perintah
sudo mount -a
view raw gistfile1.txt hosted with ❤ by GitHub

3.) Install MPICH pada shared direktori (/home/latprog/nfsprog)

Seluruh eksekusi pada langkah ini dilakukan di Head Node. Pertama, download dulu source code MPICH di alamat ini. Taruh file yang telah di download tersebut di direktori /home/latprog/nfsprog lalu eksekusi perintah berikut.

tar xzvf mpich-X.Y.Z.tar.gz
cd mpich-X.Y.Z
./configure --prefix=/home/latprog/nfsprog/mpich
make
make install
#ganti X Y Z dengan versi mpich yang telah di download
#pada saat tulisan ini dibuat, versi terbaru dari mpich yang bisa didowload adalah
#versi mpich-3.2.1
view raw gistfile1.txt hosted with ❤ by GitHub

Setelah MPICH sukses terinstall, masukkan direktori bin milik MPICH ke environment variabel PATH dengan cara
echo 'PATH=$PATH:/home/latprog/nfsprog/mpich/bin' >> ~/.bashrc
source ~/.bashrc
view raw gistfile1.txt hosted with ❤ by GitHub

4.) Set SSH tanpa password untuk Head Node ke seluruh Slave Node

Ini diperlukan karena dalam penggunaan MPI nantinya, Head Node yang akan menghubungi seluruh Slave Node untuk koordinasi pengerjaan komputasi yang harus dilakukan. Sebelum itu, seluruh slave node harus membuat direktori .ssh didalam direktori home (/home/latprog) miliknya. Setelah itu pada Head Node, generate key ssh tanpa password (ketika disuruh masukkan password, langsung tekan enter) dengan perintah sebagai berikut.

ssh-keygen -t rsa
view raw gistfile1.txt hosted with ❤ by GitHub

Lalu setelah itu kirimkan key yang telah digenerate tersebut dari Head Node ke seluruh Slave Node.
cat .ssh/id_rsa.pub | ssh latprog@192.168.1.2 'cat >> .ssh/authorized_keys'
cat .ssh/id_rsa.pub | ssh latprog@192.168.1.3 'cat >> .ssh/authorized_keys'
cat .ssh/id_rsa.pub | ssh latprog@192.168.1.4 'cat >> .ssh/authorized_keys'
view raw gistfile1.txt hosted with ❤ by GitHub

5.) Buat hostfile MPI untuk mengatur jumlah core yang digunakan untuk masing-masing Head Node dan Slave Node

Langkah ini dilakukan pada Head Node (kecuali untuk pengecekan jumlah core). Untuk melihat ada berapa core yang bisa kita gunakan (core = core sebenarnya x thread), gunakan perintah lscpu pada masing-masing seluruh Head Node dan Slave Node. Pada baris CPU(s) tercantum jumlah core yang bisa kita gunakan. Pada contoh kasus di sini, core yang bisa digunakan oleh semua komputer (Head Node dan Slave Node) masing-masing ada 4. Dengan pengetahuan ini, selanjutnya kita buat suatu file kosong didalam direktori (/home/latprog/nfsprog) beri nama hostfile (bisa bebas sebenarnya) dan isi file tersebut sebagai berikut.

192.168.1.1:4
192.168.1.2:4
192.168.1.3:4
192.168.1.4:4
view raw gistfile1.txt hosted with ❤ by GitHub

6.) Test drive

Dan kita telah selesai untuk setup parallel programming menggunakan MPI dan NFS. Untuk test drivenya, mari kita buat script sederhana untuk mengetes apakah setup kita berhasil atau tidak. Buat file baru bernama hello.c (ya, kita akan menggunakan bahasa C untuk test drive ini) dan isi file tersebut adalah sebagai berikut.

// Author: Wes Kendall
// Copyright 2011 www.mpitutorial.com
// This code is provided freely with the tutorials on mpitutorial.com. Feel
// free to modify it for your own use. Any distribution of the code must
// either provide a link to www.mpitutorial.com or keep this header intact.
//
// An intro MPI hello world program that uses MPI_Init, MPI_Comm_size,
// MPI_Comm_rank, MPI_Finalize, and MPI_Get_processor_name.
//
#include <mpi.h>
#include <stdio.h>
int main(int argc, char** argv) {
// Initialize the MPI environment. The two arguments to MPI Init are not
// currently used by MPI implementations, but are there in case future
// implementations might need the arguments.
MPI_Init(NULL, NULL);
// Get the number of processes
int world_size;
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
// Get the rank of the process
int world_rank;
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
// Get the name of the processor
char processor_name[MPI_MAX_PROCESSOR_NAME];
int name_len;
MPI_Get_processor_name(processor_name, &name_len);
// Print off a hello world message
printf("Hello world from processor %s, rank %d out of %d processors\n",
processor_name, world_rank, world_size);
// Finalize the MPI environment. No more MPI calls can be made after this
MPI_Finalize();
}
view raw gistfile1.txt hosted with ❤ by GitHub

Compile dan jalankan source code (pada direktori /home/latprog/nfsprog menggunakan Head Node) sehingga hasilnya akan terlihat mirip sebagai berikut.
mpicc hello.c -o hello
mpirun --hostfile /home/latprog/nfsprog/hostfile -np 16 ./hello
Hello world from processor 192.168.1.1, rank 0 out of 16 processors
Hello world from processor 192.168.1.3, rank 2 out of 16 processors
Hello world from processor 192.168.1.4, rank 3 out of 16 processors
Hello world from processor 192.168.1.2, rank 1 out of 16 processors
Hello world from processor 192.168.1.3, rank 4 out of 16 processors
Hello world from processor 192.168.1.2, rank 7 out of 16 processors
Hello world from processor 192.168.1.1, rank 6 out of 16 processors
Hello world from processor 192.168.1.4, rank 5 out of 16 processors
Hello world from processor 192.168.1.1, rank 15 out of 16 processors
Hello world from processor 192.168.1.1, rank 14 out of 16 processors
Hello world from processor 192.168.1.4, rank 11 out of 16 processors
Hello world from processor 192.168.1.3, rank 12 out of 16 processors
Hello world from processor 192.168.1.3, rank 10 out of 16 processors
Hello world from processor 192.168.1.2, rank 13 out of 16 processors
Hello world from processor 192.168.1.2, rank 9 out of 16 processors
Hello world from processor 192.168.1.4, rank 8 out of 16 processors
view raw gistfile1.txt hosted with ❤ by GitHub

Di sini saya bilang mirip karena setiap kali running urutan keluaranya akan selalu beda karena masing-masing core akan berlomba-lomba menjadi yang paling duluan menyelesaikan tugasnya. Jika memang benar keluarannya seperti itu berarti bisa dipastikan setup yang telah kita persiapkan telah berhasil dan siap digunakan.

Sekian tutorial kali ini. Tulisan kali ini tidak membahas tentang bagaimana melakukan parallel programming dan codingnya, mungkin lain kali yah~

referensi:
https://www.digitalocean.com/community/tutorials/how-to-set-up-an-nfs-mount-on-ubuntu-16-04, diakses pada 27 Mei 2018
https://www.digitalocean.com/community/tutorials/how-to-add-and-delete-users-on-ubuntu-16-04, diakses pada 27 Mei 2018
http://mpitutorial.com/tutorials/mpi-hello-world/, diakses pada 28 Mei 2018

Komentar