Programlama | Programlama Dilleri | C Programlama Dili |C++

Anasayfa Dokümanlar Kütüphane Kurulumları MPI ile Paralel Programlama


MPI ile Paralel Programlama

MPI İLE PARALEL PROGRAMLAMA

 

MPI ile Dinamik Yük Dağılımı Uygulaması

 


 

MPI Nedir?

Message Passage Interface: Dağıtık bellekli, mesaj geçmeli paralel hesaplamalarda standart oluşturabilecek mesaj geçme kütüphaneleri için bir tanımlamadır.

MPI’ın hedefi mesaj geçmeli programlar yazmak için geniş kullanıma sahip bir standart sağlamaktır. Arayüz; mesaj geçme için pratik, taşınabilir, etkin ve esnek bir standart kurmaya çalışır.

 

MPI Kullanmanın 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ı implementasyonları performansı optimum edebilmek için donanım özelliklerini en üst düzeyde kullanabilecek şekildedir.

-                    Fonksiyonellik: 115’in üzerinde rutin ile.

-                    Kullanırlık: Bir çok implementasyonu vardır.

 

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: 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 rutin kümesini belirtir.

Send/Receive: Mesaj geçme verinin bir süreçten diğer bir sürece transfer olmasını icap ettirir. Yollayan ve alan süreçlerin birlikte çalışmasını gerektirir. Send işlemleri genellikle yollayan 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ı process’in 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: Yollanacak veya alınacak veriyi tutan adres uzayıdır.

Sistem Tamponu: Mesajları tutmak için kullanılan sistem uzayıdır. Sen/Receive işlemine bağlı olarak uygulama tamponundaki veri, sistem tampon uzayından kopyalanmak zorunda kalabilir. Haberleşmenin asenkron olmasına izin verir.

Blocking Communication

Eğer çağrının tamamlanması belirli bir olaya bağlı ise haberleşme rutini 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 kullanmak için hazır olacaktır.

 

Non-Blocking Communication

Eğer çağırma herhangi bir haberleşme olayının tamamlanmasını beklemeden dönüyorsa haberleşme rutini 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 rutinleri communicator’ı argüman olarak belirtmenizi gerektirir.

MPI_COMM_WORLD, bütün MPI süreçlerini içeren önceden tanımlı ileticidir.

Rank

İleticinin içinde, her süreç başlatımlandığında sistem tarafından atanan kendi eşsiz integer belirtecine sahiptir. Rank bazen “process ID” olarak da adlandırılabilirler. Ranklar sıralıdır ve 0’dan başlarlar.

Programcı tarafından mesajın kaynağını ve hedefini belirtmek için kullanılırlar. Bir çok zaman program icrasını kontrol için uygulama tarafından şartlı olarak kullanılırlar. (if rank==0 do this / if rank==1 do that)

 

MPI’a Giriş

 

MPI kütüphane fonksiyonlarını kullanmak için header dosyasını include etmeliyiz.

#include "mpi.h"

 

MPI Çağrılarının formatı şu şekildedir:

rc = MPI_Xxxxx(parameter, ... )

 

Genel MPI Programı Yapısı şu şekilde olmaktadır:

 

MPI include file

 


.
.

 

Initialize MPI environment

 


.
.

 

Do work and make message passing calls

 


.
.

 

Terminate MPI Environment

 

Yaygın Kullanılan MPI Fonksiyonları:

MPI_Init(&argc,&argv) 

MPI_Init fonksiyonunu bütün kodlarınıza eklemeniz gerekmektedir. MPI_Init fonksiyonuna komut satırından da parametre verebilirsiniz ama mecbur değilsiniz. MPI_Init size bir değer dönmektedir bu “MPI_SUCCESS” olursa kod geri kalan MPI_X fonksiyonlarını kullanabilecektir, eğer bu değer dönmezse MPI_X fonksiyonlarını kullanamazsınız.

MPI_Comm_size(comm,&size) 

Bu fonksiyonumuz proses sayısını bize vermektedir. Genellikle “comm” kısmına MPI_COMM_WORLD üst fonksiyonu yazılmaktadır.

MPI_Comm_rank(comm,&rank)

Bu MPI fonksiyonu çağıran prosesin sırasını vermektedir. Başlangıçta bütün prosesler 0 veya -1 değerlerini almaktadır. Daha sonra MPI tarafından sıraya sokulunca bütün prosesler numaralandırılmaktadır. Aşağıda ki örneğimizde göreceğimiz gibi makineler 0 dan başlayarak rank(sıra) alacaklardır.

MPI_Abort (comm,errorcode)

Adından da anlaşıldığı gibi bütün prosesleri durdurmaktadır. Istenmeyen durumlarda başvurulabilecek bir fonksiyondur.

MPI_Get_processor_name(&name,&resultlength)

İşlemcinin adını ve adın uzunluğunu dönmektedir.

MPI_Initialized(&flag) 

MPI_Init fonksiyonun çağırılıp çağırılmadığını kontrol etmektedir ve çağırıldıysa “1” dönmektedir. MPI_Init her proses tarafından sadece bir kere çağırılması gerektiği için MPI_Initialized fonksiyonu olası çakışmaları önlemektedir.

MPI_Wtime( ) 

Double deger olarak paralel kodun çalışmaya başlamasından sonra geçen zamanı vermektedir.

MPI_Finalize( )

Bütün işlemlerimizden sonra MPI_Finalize diyerek işlemlerimizi sonlandırıyoruz.

MPI_Send(&buffer,count,datatype,dest,tag,comm) 

MPI_Recv(&buffer,count,datatype,source,tag,comm,status) 

Fonksiyonlarımız burada değişik parametreler almaktadır bunlardan buffer yollanacak veya alınacak verinin adresini göstermektedir. Count parametresi yollanacak verilerin sayısını belirtmektedir. Datatype parametresi gidecek verinin türünü belirtmektedir (int,float,char,...). Dest parametresi verinin hangi makineye gideceğini belirtmektedir. Source parametresi verinin hangi makineden alacağını belirtmektedir.Tag parametresi ise 0-32767 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.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. Şu anlık bu değer yeterlidir. Grup haberleşme fonksiyonlarında ise comm parametresi birden fazla değer alabilir. En son parametre değerimiz ise RECV fonksiyonundaki status değeridir. Status mesajın geldiği kaynağı bize bildirmektedir.

SEND/RECV fonksiyonlarımızın dışında işimize yarayabilecek başka fonksiyonlarda vardır bunları kısaca inceleyecek olursak;

MPI_Isend(&buffer,count,datatype,dest,tag,comm) 

MPI_Irecv(&buffer,count,datatype,source,tag,comm,status)

Yukarıda gördüğünüz komutların Send ve Recv fonksiyonlarından tek farkı “I” (Immediate) yani beklemeksizin veri alışverişlerin olmasıdır. Sizin de tahmin edebileceğiniz gibi, Send/Recv fonksiyonlarında var olan otomatik olarak bekleme işlemi burada kullanıcı inisiyatifine bırakılmaktadır. Bu fonksiyonlar tek başlarına kullanılmazlar. Muhakkak MPI_WAIT veya MPI_TEST gibi yardımcı fonksiyonları kullanmaları gerekmektedir.

MPI_Wait(&request,&status) 

ISEND ve IRECV fonksiyonları verileri yollayana veya alana kadar beklemelerini sağlayan fonksiyondur. Status istenilen mesajın adresini ve tag’ ini dönmektedir.

MPI_Test (&request,&flag,&status)

Bu fonksiyonumuz da istenilen verinin ulaşıp ulaşmadığını kontrol etmek için kullanılır. Eğer verimiz istenilen yere ulaşmışsa flag olarak true değeri  dönmektedir. Status istenilen mesajın adresini ve tag’ ini dönmektedir.

MPI_Reduce(data, result, count, type, op, root,comm) 

Bu fonksiyonumuz N tane makinede oluşmuş sonuçları derleyerek ana proses’ te 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 alınma işlemlerinin sonuçlarını, root verilerin alındığı prosesleri ve son olarak comm haberleşme ortamının adını (MPI_COMM_WORLD) almaktadır.

Yukarıda da gördüğümüz gibi 5 tane işlemci ayrı data yani veriler üretmektedir. İstersek bunları ayrı ayrı yollayabiliriz. Bunun için her makine send/recv fonksiyonlarını kullanabiliriz. Biz bunun yerine MPI_REDUCE fonksiyonunu kullanıyoruz. Elimizde ki bütün “data” verilerini MPI_REDUCE aracılığı ile ana işlemcide “result” dizisine gönderiyoruz. 

 

 

 

MPI_AllReduce(data, result, count, type, op, root,comm)

ALLREDUCE fonksiyonu REDUCE ile işlevsel olarak aynıdır. Tek farkı bütün proseslere result değerini göndermektedir.

MPI_Barrier(comm) 

Global haberleşme fonksiyonlarının en önemlilerindendir. Bütün proseslerin işlemleri tamamlanana kadar devam etmelerini engelleyen senkronizasyon fonksiyonudur.

MPI_Bcast(&buffer,count,datatype,root,comm) 

BCAST, Broadcasting kelimesinin kısaltılmış halidir. Root olarak sayılan prosesten arabellekteki (buffer) değerleri “comm” ortamında ki bütün proseslere yollamaktadır. İlk yazımda yazdığım gibi MPI paralel makineler arası haberleşme kütüphanesidir ve 100 den fazla fonksiyonu vardı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 tasktan ayrı mesajları alır ve tek hedefe toplar. Bu rutin MPI_Scatter’ın ters işlemidir.

 

Önceden tanımlı MPI indirgeme işlemleri şunlardır:

MPI Reduction Operation

C data types

Fortran data types

MPI_MAX

maximum

integer, float

integer, real, complex

MPI_MIN

minimum

integer, float

integer, real, complex

MPI_SUM

sum

integer, float

integer, real, complex

MPI_PROD

product

integer, float

integer, real, complex

MPI_LAND

logical AND

integer

logical

MPI_BAND

bit-wise AND

integer, MPI_BYTE

integer, MPI_BYTE

MPI_LOR

logical OR

integer

logical

MPI_BOR

bit-wise OR

integer, MPI_BYTE

integer, MPI_BYTE

MPI_LXOR

logical XOR

integer

logical

MPI_BXOR

bit-wise XOR

integer, MPI_BYTE

integer, MPI_BYTE

MPI_MAXLOC

max value and location

float, double and long double

real, complex,double precision

MPI_MINLOC

min value and location

float, double and long double

real, complex, double precision

 

MPI Argümanları

Buffer: Yollanacak veya alınacak veriyi referanslayan program adres uzayıdır.

Data Count: Yollanacak olan belirli bir tipteki veri elemanı sayısıdır.

Data Type: Taşınabilirlik için MPI kendi veri tiplerini tanımlamıştır:

 

MPI-C 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

data packed or unpacked with MPI_Pack()/ MPI_Unpack

 

Destination: Send rutinlerinde kullanılan bir argüman olup, mesajın nereye ulaştırılacağını belirtir. Alıcı process’in rank’ı ile tanımlanır.

Source: Mesajın nereden geldiğini belirtir. Bu argüman herhangi bir süreçten mesaj almak için MPI_ANY_SOURCE wild card’ına ayarlanabilir.

Tag: Mesajı unique olarak tanımlamak için programcı tarafından gelişigüzel atanan, negatif olmayan bir sayıdır. Send ve receive işlemleri mesaj tag’larında eşleşmelidir. Receive işlemi için MPI_ANY_TAG wild card’ı kullanılabilir. MPI standart 0-32767 arasındaki sayıların kullanılabilmesini garanti eder.

Communicator: Haberleşme içeriğini veya kaynak ve hedef alanları geçerli bir grup süreci işaret eder. Programcı açıkça yeni bir communicator oluşturmadıkça önceden tanımlanmış MPI_COMM_WORLD kullanılır.

Status: Receive işlemi için mesajın kaynağını ve mesajın tag’ını belirtir. C’de bu argüman önceden tanımlı MPI_Status yapısına (MPI_SOURCE ve MPI_TAG elemanlarını içerir) bir pointer’dır.

Yorumlar (0)
Sadece kayıtlı kullanıcılar yorum yazabilir!
 
amınıza koyayım amınıza koyayım amınıza koyayım amınıza koyayım amınıza koyayım amınıza koyayım