Mesaj Geçiren Arayüz (MPI (Message
Passage Interface))
Dağıtık bellekli, mesaj geçiren paralel
hesaplamalarda standart oluşturabilecek mesaj geçirme kütüphaneleri için bir
tanımlamadır. MPI’ın hedefi mesaj geçiren programlar yazmak için geniş
kullanıma sahip bir standart sağlamaktır.
MPI Kullanma Nedenleri
Standartlaştırma:
MPI, standart sayılabilecek tek mesaj geçme kütüphanesidir. Bütün HPC
platformlarında desteklenmiştir.
Taşınabilirlik:
MPI destekleyen başka bir platforma uygulamanızı taşıdığınız zaman kodunuzu
değiştirmeye gerek yoktur.
Performans:
Satıcı uygulamaları, performansı optimum edebilmek için donanım
özelliklerini en üst düzeyde kullanabilecek şekilde tasarlanmıştır.
Fonksiyonellik:
Üzerinde
115 fonksiyon bulunur.
Kullanılabilirlik:
Bir çok uygulama alanı vardır.
MPI Kütüphaneleri Karşılaştırılması
MPI kütüphanelerinin işlem, donanım, işletim sistemi, ağ ara bağlantıları ve hatta
özel uygulamalar için farklı türleri vardır. MPICH2, MPICH ile,
OpenMPI, Intel MPI, MS-MPI, LAM / MPI ve diğerleri arasında karşılaştırmalar yapılabilir, Özel kullanıma uygun
kütüphaneleri seçmenin birçok zorluğu bulunuyor. MPI kütüphanelerinden ücretsiz bir alternatif arayanlar MPICH2, ücretli alternatif ise Intel MPI kullanılabilir durumdadır. Intel MPI, EC2 üzerinde yoğun testlerden geçirilmiştir ve Intel tarafından önerilir. Genel olarak uygulamalar EC2 üzerinde iyi performansla çalışır, ancak özel uygulamalar için daha iyi başka bir
kütüphaneler kullanabilir.
|
MPI
Performansı Etkileyen Faktörler
Platform/Mimari
ile İlgili
CPU
CPU
1. Saat Hızı
2. İşlemci Sayısı
Bellek
Alt Sistemi
1. Bellek ve Önbellek Yapılandırması
2. Hafıza - Cache - Cpu Bant Genişliği
3. Bellek Kopyalama Bant Genişliği
İşletim
Sistemi Özellikleri
Ağ
ile İlgili
Donanım
Donanım
1. Ethernet
2. Switch
3. Router
Protokoller
TCP / IP /
UDP
Uygulama
ile İlgili
1. Algoritma Verimliliği ve Ölçeklenebilirlik
2. Hesaplama/İletişim Oranı
3. Yük Dengeleme
4. Bellek Kullanım Şekilleri
5. I / O
6. Mesaj Boyutu
MPI Fonksiyon Kategorilendirme
İlklendirme ve
Sonlandırma Fonksiyonları (Initialization / Finalization Functions)
Noktadan
Noktaya İletişim Fonksiyonları (Point-to-Point Communication
Functions)
Topluluk
İletişim Fonksiyonları (Collective Communication Functions)
İletici
Topolojilerinin Fonksiyonları (Communicator Topologies Functions)
Kullanıcı
Tanımlı Fonksiyonlar (User Defined Functions)
Yardımcı
Fonksiyonlar (Utilities Functions)
Mesaj Geçme Modeli
Dağıtık
Bellek: Her işlemci sadece kendi CPU’su ile direk
olarak erişilebileceği yerel belleğe sahiptir. Bir işlemciden diğerine veri
iletimi ağ üzerinden gerçekleştirilir.
Mesaj
Geçme İşlemi: Verinin bir işlemcinin
belleğinden diğer bir işlemcinin belleğine kopyalandığı yöntemdir. Dağıtık
bellekli sistemlerde veri genellikle bir işlemciden diğerine ağ üzerinden bilgi
paketleri olarak yollanır. Bir mesaj bir veya daha çok bellekten oluşabilir ve
çoğunlukla yönlendirme ya da başka kontrol bilgileri içerir.
Mesaj
Geçme Kütüphanesi: Uygulama kodunun içine gömülen
bir fonksiyon kümesini belirtir.
Send/Receive: Mesaj
geçme verinin bir süreçten diğer bir sürece transfer olmasını gerektirir. Send
ve Receive süreçlerin birlikte çalışmasını gereklidir. Send işlemleri
genellikle Send sürecin verinin yeri, boyu, tipi ve hedefi bilgilerini
belirtmesini gerektirir. Receive işlemleri ilişkili Send işlemi ile
eşleşmelidir.
Senkron
/ Asenkron: Senkron Send işlemi alıcı işlemin mesajı
güvenli bir şekilde aldığını belirten onayından sonra sonlanacaktır. Asenkron Send
işlemleri alıcı süreç mesajı almadan tamamlanabilir.
Uygulama
Tamponu: Gönderilecek veya alınacak veriyi tutan
adres uzayıdır.
Sistem
Tamponu: Mesajları tutmak için kullanılan sistem
uzayıdır. Send/Receive işlemine bağlı olarak uygulama tamponundaki veri, sistem
tampon uzayından kopyalanmak zorunda kalabilir. Haberleşmenin asenkron olmasına
izin verir.
Bloklanan İletişim (Blocking
Communication)
Eğer çağrının tamamlanması belirli bir olaya bağlı
ise haberleşme fonksiyonu bloklanır. Göndermeler için, veri başarı ile
yollanmalı veya sistem tampon uzayına güvenli bir şekilde kopyalanmalıdır.
Alıcı için veri, alıcı tamponunda depolanmalıdır. Böylece veri her an
kullanılmak için hazır olacaktır.
Bloklanmayan İletişim (Non-Blocking
Communication)
Eğer çağırma herhangi bir haberleşme olayının
tamamlanmasını beklemeden dönüyorsa haberleşme fonksiyonu bloklanmayandır. Bloklanmayan
haberleşmeler performansı arttırmak amacıyla hesaplamayı haberleşme ile üst
üste getirmek için kullanılırlar.
İleticiler ve Gruplar
MPI hangi süreç kümelerinin hangileri ile
haberleşeceğini belirtmek için, communicator ve group adında nesneler
kullanırlar. Çoğu MPI fonksiyonları communicator’ı argüman olarak belirtmenizi
gerektirir.
MPI_COMM_WORLD, bütün MPI süreçlerini içeren
önceden tanımlı ileticidir.
MPI_COMM_WORLD Simülasyonu |
Rank
İleticinin içinde, süreç her defasında
başlatıldığında sistem tarafından atanan kendi eşsiz integer belirtecine
sahiptir. Rank bazen process ID olarak da adlandırılabilir. Ranklar
sıralıdır ve 0’dan başlarlar.
Geliştirici tarafından mesajın kaynağını ve hedefini
belirtmek için kullanılır. Çoğu zaman kontrol için if-else yapısıyla kullanılır.
Yaygın Kullanılan MPI Fonksiyonları
MPI_Init(&argc,&argv)
MPI_Init fonksiyonunu bütün kodlara eklemek gereklidir. MPI_Init fonksiyonuna komut satırından da parametre
verilebilir. MPI_Init bir değer döndürecektir, bu değer MPI_SUCCESS olursa kodda geri kalan MPI_X fonksiyonlarını kullanabilecektir,
eğer bu değer dönmezse MPI_X fonksiyonlarını kullanılamaz.
MPI_Comm_size(comm,&size)
Bu fonksiyon işlem sayısını verir. Genellikle comm kısmına MPI_COMM_WORLD üst fonksiyonu yazılmaktadır.
MPI_Comm_rank(comm,&rank)
Bu MPI fonksiyonu çağıran işlemin sırasını
vermektedir. Başlangıçta bütün işlemler 0 veya -1 değerlerini alır, sonrasında MPI tarafından sıralanınca bütün işlemler numaralandırılmaktadır.
MPI_Abort (comm,errorcode)
Adından da anlaşıldığı gibi bütün işlemleri
durdurmaktadır. İstenmeyen durumlarda başvurulabilecek bir fonksiyondur.
MPI_Get_processor_name(&name,&resultlength)
İşlemcinin adını ve adın uzunluğunu vermektedir.
MPI_Initialized(&flag)
MPI_Init fonksiyonun çağırılıp, çağırılmadığını
kontrol etmektedir ve çağırıldıysa '1' değeri dönmektedir. MPI_Init her işlem
tarafından sadece bir kere çağırılması gerektiği için MPI_Initialized
fonksiyonu olası çakışmaları önlemektedir.
MPI_Wtime( )
Double değer olarak paralel kodun çalışmaya
başlamasından sonra geçen zamanı vermektedir.
MPI_Finalize( )
Bütün işlemlerden sonra MPI_Finalize ile işlemler
sonlandırılır.
MPI_Send(&buffer,count,datatype,dest,tag,comm)
MPI_Recv(&buffer,count,datatype,source,tag,comm,status)
Fonksiyonlar farklı parametreler alabilir. Bunlar:
1. buffer gönderilecek veya alınacak verinin
adresini göstermektedir.
2. count parametresi gönderilecek verilerin
sayısını belirtmektedir.
3. datatype parametresi gönderilecek verinin
türünü belirtmektedir(int,float,char vb.).
4. dest parametresi verinin hangi makineye
gönderileceğini belirtmektedir.
5. source parametresi verinin hangi makineden
alacağını belirtmektedir.
6. tag parametresi ise -2147483648 - 2147483647 arası sayısal bir
değer alır ve kullanıcı tarafından yanlış makinelerden mesajlar gelmesini
önlemek için verilebilecek bir tür güvenlik kodudur. Send ve Recv
fonksiyonlarında tag’lerin eşit olması gerekmektedir.
7. comm değişkeni olarak genelde MPI_COMM_WORLD
kullanılmaktadır. Grup haberleşme fonksiyonlarında değişik comm değerleri
kullanılmaktadır. Grup haberleşme fonksiyonlarında ise comm parametresi birden
fazla değer alabilir.
8. status mesajın geldiği kaynağı bildirmektedir.
MPI_Isend(&buffer,count,datatype,dest,tag,comm)
MPI_Irecv(&buffer,count,datatype,source,tag,comm,status)
Send ve Recv fonksiyonlarından tek farkı I (Immediate) yani beklemeksizin veri alışverişlerinin olmasıdır. Yani Send/Recv
fonksiyonlarında var olan otomatik olarak bekleme işlemi bu fonksiyonlarda kullanıcı
isteğine bırakılmaktadır. Bu fonksiyonlar tek başlarına kullanılmazlar. MPI_Wait
veya MPI_Test gibi yardımcı fonksiyonları kullanmaları gerekmektedir.
MPI_Wait(&request,&status)
ISEND ve IRECV fonksiyonları verileri gönderene
veya alana kadar beklemelerini sağlayan fonksiyondur. status istenilen mesajın
adresini ve tag’ini geriye döndürmektedir.
MPI_Test
(&request,&flag,&status)
Bu fonksiyon istenilen verinin ulaşıp ulaşmadığını
kontrol etmek için kullanılır. Eğer veri istenilen yere ulaşmışsa flag olarak
true değeri geriye dönmektedir. status istenilen mesajın adresini ve tag’ini dönmektedir.
MPI_Reduce(data, result, count, type,
op, root,comm)
Bu fonksiyon n tane makinede oluşmuş sonuçları
derleyerek ana işlemcide result dizisinde saklamaktadır. Geri kalan
değişkenlerden count reduce (alınmış veri) sayısını, type alınan verilerin
türlerini, op yapılan alma işlemlerinin sonuçlarını, root verilerin
alındığı işlemcileri ve son olarak comm haberleşme ortamının adını
(MPI_COMM_WORLD) almaktadır.
MPI_Allreduce(data, result, count,
type, op, root,comm)
Allreduce() fonksiyonu Reduce() ile işlevsel olarak
aynıdır. Tek farkı bütün işlemcilere result değerini göndermektedir.
MPI_Barrier(comm)
Global haberleşme fonksiyonlarının en önemlilerindendir.
Bütün işlemcilerin işlemleri tamamlanana kadar devam etmelerini engelleyen
senkronizasyon fonksiyonudur.
MPI_Bcast(&buffer,count,datatype,root,comm)
Bcast, Broadcasting kelimesinden türetilmiştir.
Root olarak sayılan işlemciden arabellekteki (buffer) değerleri comm ortamında
ki bütün işlemcilere yollamaktadır.
MPI_Scatter (*sendbuf, sendcnt,
sendtype, *recvbuf, recvcnt, recvtype, root, comm)
Tek bir kaynak task’tan gruptaki her bir task’a
ayrı mesajların dağıtılmasını sağlar.
MPI_Gather (*sendbuf, sendcnt,
sendtype, *recvbuf, recvcount, recvtype, root, comm)
Gruptaki her bir task’tan ayrı mesajları alır ve
tek hedefe toplar. Bu fonksiyon MPI_Scatter’ın ters işlemidir.
MPI Veri Tipleri (Data Types)
|
|
MPI_CHAR
|
signed char
|
MPI_SHORT
|
signed short int
|
MPI_INT
|
signed int
|
MPI_LONG
|
signed long int
|
MPI_UNSIGNED_CHAR
|
unsigned char
|
MPI_UNSIGNED_SHORT
|
unsigned short int
|
MPI_UNSIGNED
|
unsigned int
|
MPI_UNSIGNED_LONG
|
unsigned long int
|
MPI_FLOAT
|
float
|
MPI_DOUBLE
|
double
|
MPI_LONG_DOUBLE
|
long double
|
MPI_BYTE
|
8 binary digits
|
MPI_PACKED
|
MPI_Pack()/ MPI_Unpack() (veri paketleme ya da açma)
|
Cluster düğümleri üzerinde çalıştırılacak kod bloğu:
#include <mpi.h> //MPI Rutinlerini Kullanabilmek Icin #include#include using namespace std; int main(int argc, char* argv[]) { /*Initialize the MPI execution environment*/ MPI_Init(&argc,&argv); printf("Hello World!"); /* Terminate the MPI execution environment*/ MPI_Finalize(); return 0; }
MPICH2''nun MPI fonksiyonlarını içeren C++ kodlarını derleyebilmek için mpicxx yada mpic++ komutları kullanılır.
[btahtacioglu@admin Examples]$ mpicxx Hello_World.cpp
[btahtacioglu@admin Examples]$ mpic++ Hello_World.cpp [btahtacioglu@admin Examples]$ ls Hello_World.cpp a.outmpirun komutuyla çalıştırılabilir dosyanın çalışması kontrol edilir. (Sanal makineler üzerinde)
[btahtacioglu@admin Examples]$ mpirun -np 4 ./a.out Hello World Hello World Hello World Hello WorldMPICH2'nun MPI fonksiyonlarını içeren C++ kodlarını cluster düğümleri üzerinde çalıştırmak için mpiexec komutu kullanılır.
[btahtacioglu@admin Examples]$ mpiexec -f ~/cluster_hosts -n 4 ./a.out Hello World Hello World Hello World Hello World
Bloklanan iletişim için cluster düğümleri üzerinde çalıştırılacak kod bloğu:
[btahtacioglu@admin Examples]$ mpicxx Send_Receive_Message.cpp [btahtacioglu@admin Examples]$ mpiexec -f ~/cluster_hosts -n 2 ./a.out Process 0 mesaj gonderdi Process 1 mesaji aldi. a adli dizinin 1 nolu process deki 2. elemani : 1