Paralel Programlama IV (Parallel Programming IV)

watch_later 3/16/2016
comment 2 Comments
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.

MPICH2 ve Intel MPI Karşılaştırılması


MPI Performansı Etkileyen Faktörler
Platform/Mimari ile İlgili
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
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.

MPI Programının Minimum İskeleti



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.out
mpirun 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 World 
MPICH2'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


 Send_Receive_Message.cpp



Bir sonraki yazımda görüşmek üzere...
avatar
Adsız

Çok teşekkür ederim Burak bey çalışmalarınızın devamını dilerim...

delete 22 Mart 2016 07:42
avatar

Yorumunuz için teşekkürler...

delete 22 Mart 2016 08:25



sentiment_satisfied Emoticon