OpenMPI

OpenMPI adalah serangkaian Application Programming Interface (API) yang dapat digunakan untuk melakukan paralelisasi untuk C, C++, dan Fortran. Penggunaan OpenMPI akan sedikit lebih sulit dibanding OpenMP dikarenakan sistem paradigma memori terdistribusi (distributed memory) yang digunakan oleh OpenMPI.

Karena memori yang digunakan oleh program OpenMPI dikelola oleh masing-masing proses yang berjalan secara paralel, program dapat dijalankan pada beberapa unit komputer (node) sekaligus. Hal ini memungkinkan eksekusi program yang jauh lebih besar dibanding OpenMP.

Kelemahan dari OpenMP adalah kita harus mendesain komunikasi antar proses secara eksplisit. Hal ini dapat dilakukan dengan menggunakan panggilan fungsi yang disediakan oleh OpenMPI.

Dasar OpenMPI

Untuk memulai penggunaan OpenMPI, kita dapat melakukan kompilasi dengan wrapper mpicc atau mpifort:

mpicc program.c -o program
mpiifort program.f90 -o program

memanggil program yang terkompilasi dengan:

mpirun -np N ./program

Nilai N adalah jumlah proses yang akan dijalankan. Jika N tidak didefinisikan, maka OpenMPI akan menjalankan program dengan jumlah proses yang sama dengan jumlah core yang tersedia.

Untuk memulai penggunaan OpenMPI, kita harus memanggil fungsi:

MPI_Init(&argc, &argv);

Fungsi ini akan menginisialisasi OpenMPI dan mengalokasikan sumber daya yang dibutuhkan. Variabel MPI_COMM_WORLD akan terdefinisi setelah fungsi ini yang berisi referensi untuk komunikator proses yang berjalan.

Setelah selesai, kita dapat menggunakan:

MPI_Finalize();

Untuk mengetahui total jumlah proses yang dijalankan dan rank dari proses yang berjalan kita menggunakan:

MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);

Perlu diingat bahwa semua variabel akan bersifat private.

Komunikasi Antar Proses

Komunikasi antar proses dapat dilakukan dengan menggunakan fungsi:

MPI_Send(&data, count, MPI_TYPE, dest, tag, MPI_COMM_WORLD);
MPI_Recv(&data, count, MPI_TYPE, source, tag, MPI_COMM_WORLD, &status);
MPI_Sendrecv(&send_data, send_count, MPI_TYPE, dest, send_tag, &recv_data, recv_count, MPI_TYPE, source, recv_tag, MPI_COMM_WORLD, &status);

MPI_TYPE adalah tipe data yang akan dikirim. Contoh: MPI_INT, MPI_DOUBLE, MPI_FLOAT, dan lain-lain.

count adalah jumlah data yang akan dikirim.

dest adalah rank dari proses tujuan.

source adalah rank dari proses sumber.

tag adalah tag yang akan digunakan untuk mengidentifikasi pesan.

status adalah status dari pesan yang diterima.

Selain kedua fungsi ini, juga terdapat fungsi yang tidak memblokir proses yang sedang berjalan:

MPI_Isend(&data, count, MPI_TYPE, dest, tag, MPI_COMM_WORLD, &request);
MPI_Irecv(&data, count, MPI_TYPE, source, tag, MPI_COMM_WORLD, &request);

request adalah variabel yang akan menyimpan status dari fungsi yang dipanggil.

Untuk menunggu proses yang sedang berjalan, kita dapat menggunakan:

MPI_Wait(&request, &status);

Komunikasi Masal

Ada beberapa komunikasi masal yang dapat dilakukan:

Fungsi Sumber Target Kegunaan
MPI_Bcast 1 banyak Membagikan satu variabel ke banyak proses.
MPI_Scatter 1 banyak Membagikan bagian dari variabel ke masing-masing proses.
MPI_Gather banyak 1 Mengumpulkan bagian variabel dari masing-masing proses.
MPI_Reduce banyak 1 Mengumpulkan satu variabel dari banyak proses ke satu proses dengan reduksi tertentu.
MPI_Allreduce banyak banyak Melakukan MPI_Reduce lalu MPI_Bcast.

MPI_Barrier

MPI_Barrier(comm) adalah fungsi yang dapat kita gunakan untuk melakukan sinkronisasi semua proses. Penggunaan fungsi ini secara berlebih mengurangi performa paralelisasi.