KARADENİZ TEKNİK ÜNİVERSİTESİ BİLGİSAYAR MÜHENDİSLİĞİ BÖLÜMÜ BİLGİSAYAR AĞLARI LABORATUARI Bilgisayar Ağları ve Dağıtık Programlama 1. Giriş Bu deneyde paralel programlama standartlarından olan MPI (Message Passing Interface) ve OpenMP (Open Multi Processing) protokollerinin öğrenilmesi ve bu protokoller kullanılarak Pi sayısının hesaplanması amaçlanmıştır. Genel amaçlı bir paralel bilgisayar sistemi, kendine ait veya paylaşımlı belleği olan birçok işlemci ya da çekirdekten oluşan bir sistemdir. Paralel bilgisayar sistemdeki her bir işlemcide ya da çekirdekte, bir veya birden fazla süreç koşmaktadır. Bu süreçler birbirleriyle mesaj-geçme yoluyla haberleşirler. Süreçler arası iletişimin miktarı dolayısıyla hesaplama/haberleşme (computation/communication) oranı, paralelleştirme sonucu elde edilecek hızlanmayı doğrudan etkilemektedir. Paralelleştirme parametreleri bu oran doğrultusunda optimize edilmelidir. 2. Paralel Programlama ve Paralel Bilgisayar Sistemleri Bir problemin algoritmik veya domain ayrıştırması yapılıp alt parçalara bölünerek daha hızlı hesaplanması, paralel programlama ve paralel bilgisayar sistemlerinde kullanılan temel hesaplama yaklaşımını tanımlamaktadır. Bu deneyde SPMD (Single Program Multiple Data) modeli yani master-slave yaklaşımı kullanılacaktır. Burada master yönetim, işlerin alt parçalara bölünmesi, iş dağıtımını ve sonuçların birleştirilmesini yaparken; slave süreçler de alt hesaplamaları yapmaktadır. 2.1. Paralel Programlama Paralel programlama, bir problemi birden fazla bilgisayar veya işlemci kullanarak daha kısa zamanda hesaplamayı hedefler. Paralel programlama ya da paralelleştirme sayesinde, donanımın ya da işletim sisteminin yetersizliği nedeniyle sıralı yöntemlerle hesaplanamayan problemler, paralel bilgisayarlar ve çoklu-threadler sayesinde kabul edilebilir zamanda veya gerçek zamanda hesaplanabilmektedir. DNA modellemesi, hava tahmini vs. gibi yoğun hesaplama gerektiren problemler, paralel programlama sayesinde kabul edilebilir zamanlarda hesaplanabilirler. Diğer yandan, değişik alanlardaki birçok araştırmacı hesaplamalarda yüksek hıza ihtiyaç duymaktadır. 2.2. Paralel Bilgisayar Sistemleri Paralel bilgisayar sistemleri, paylaşımlı ve dağıtık bellekli sistemler olmak üzere 2 ana gruba ayrılabilir. Paylaşımlı bellekli sistemlerde işlemciler ortak bir belleğe erişirler. Aynı 1
bellek bölgesine eş zamanlı erişimleri engellemek açısından senkronizasyon büyük önem taşır. Dağıtık bellekli sistemlerde ise her bir işlemci kendi belleğine sahiptir ve bir işlemci başka bir işlemcinin belleğindeki veriyi mesaj geçme (message passing) ile elde eder. Her iki sistemin de birbirlerine göre avantajları ve dezavantajları mevcuttur. Kısaca, paylaşımlı bellekli sistemler kolay programlanabilir, dağıtık bellekli bilgisayarlar ise ölçeklenebilir paralel bilgisayarlardır. Şekil 1 ve Şekil 2 de sırasıyla paylaşımlı ve dağıtık bellekli paralel bilgisayar sistemlerinin mimarisi verilmiştir: Haberleşme Ağı Paylaşımlı Bellek Şekil 1. Paylaşımlı Bellekli Paralel Bilgisayar Sistemi Bellek Bellek Bellek Haberleşme Ağı Şekil 2. Dağıtık Bellekli Paralel Bilgisayar Sistemi 3. MPI (Message Passing Interface) MPI (Message Passing Interface) protokolü, mesaj geçme yapısını kullanarak paralel programlamada kullanılan standardıdır. MPI kütüphane rutinleri ve görevleri aşağıdaki gibidir: MPI_Init(&argc,&argv): MPI protokolünün başlatılması için kullanılmaktadır. MPI_Comm_size(comm,&size): Çalışan süreç sayısını verir. MPI_Comm_rank(comm,&rank: Sistemde çalışan her bir sürecin kendine has, o sistem için tek olan bir numarası vardır. Bu bilgiyi elde etmek için kullanılır. MPI_Finalize(): MPI protokolünün sonlanması için kullanılır. MPI_Send(buffer, count, datatype, destination, tag, communicator): Mesaj göndermek için kullanılır. MPI_Recv(buffer, count, datatype, source, tag, communicator, status): MPI_Send() fonksiyonu ile gönderilen mesajları almak için kullanılır. 2
4. OpenMP (Open Multiprocessing) OpenMP, paylaşımlı bellekli çoklu işlemcili mimariler için geliştirilmiş ve derleyici direktifleri yardımıyla paralel programlama yapan bir uygulama geliştirme arayüzüdür. Derleyicide derlenen program komutlarını paralel çoklu işlemciye/çekirdeğe sahip sistemlerde dağıtır ve paralel olarak işletilmesinin sağlar. OpenMP uygulamaları C/C++ ve Fortran dilleri ile geliştirilebilir ve bu dillere ait birçok derleyici OpenMP desteği vermektedir. OpenMP programlama modelinin sahip olduğu bazı temel özellikler şöyledir: İş parçacığı tabanlı paralellik Çatallan-Birleş (Fork-Join) modeli İç içe döngüleri paralel yapabilme Dinamik iş parçacıkları Derleyici direktifleri yardımıyla paralel programlama OpenMP nin çalışma biçimi temel fork-join (çatallan-birleş) programlama modeline dayanır. Uygulamalarda, çalışan bir program tek bir iş parçacığı (thread) olarak çalışmaya başlar. Programcı eş zamanlılığı kullanmak istediğinde, iş parçacıkları (workers) oluşturulur (fork) ve bu iş parçacıkları takım halinde verilen görevi yerine getirirler. Takım halinde çalışan iş parçacıkları da sadece paralel alan dediğimiz alan içerisinde paralel olarak çalışır. Paralel alan bittiğinde, iş parçacıkları tüm iş parçacıkları bitene kadar beklerler ve birleştirilirler (join). Bu noktadan sonra master iş parçacığı yeni bir paralel bir alan tanımı ile karşılaşıncaya kadar tek olarak çalışmaya devam eder. Bu paralel çalışma yöntemi aşağıdaki görseldeki gibidir. Şekil 3. OpenMP'nin çalışma düzeni 5. Deney Hazırlığı Bu deneyde işlemci çiftliği paralel hesaplama modeli kullanılacaktır. Paralel hesaplamada veya programda hangi süreçlerin yer aldığı, süreçlerin işlemcilere nasıl dağıtıldığı, süreçler arasındaki mesaj-geçme kanalları Şekil 3 te verilmiştir. 3
Task[i] Master (PE0) (PE1) (PE2) (PE3) (PEn) Sonuç[i] Şekil 3. süreç modeli İlk olarak işlemci sayısı kadar iş, master işlemci tarafından tüm istemcilere gönderilir. Bu, başlangıçta boşta kalan istemci olmaması içindir. Daha sonra her bir istemcinin hesaplamasını tamamlaması ile iş havuzunda iş olduğu sürece yeni iş mevcut istemciye gönderilir. 6. Deney Tasarımı ve Uygulaması Bu deneyde C dilinde Pi sayısının paralel hesaplanmasının MPI ve OpenMP ile gerçekleşmesi ele alınacaktır. MPI kütüphanesini C dilinde kullanabilmek için <mpi.h> başlığının eklenmesi gerekir. Böylece paralellik için gerekli tüm rutinler kullanılabilir hale gelir. Pi sayısını hesaplamada aşağıdaki formül kullanılır: Böyle bir integral ifadesinin bilgisayarda hesaplanabilmesi için toplam ifadesine dönüştürülmesi gerekir. MPI ile Pi sayısının hesaplanmasını sağlayan programın temel kod yapısı aşağıdaki gibidir: #include <stdio.h> #include <stdlib.h> #include <mpi.h> double calculatepi (double b,double s,double N); void master(int); // Ana süreç void slaves(int); // Child süreçler int main(int argc, char *argv[]) int np, rank; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &np); if(rank ==0) 4
master (np-1); // Ana sürec başlatılır. else slaves (rank); // Worker sürecler başlatılır. MPI_Finalize(); double calculatepi (double b,double s,double N) double sonuc = 0; int i; for(i=b; i<=s; i++) double x= ((double)i-0.5)*(1/n); sonuc += 4/ (1+(x*x)); sonuc = sonuc*(1/n); return sonuc; void master(int worker) double is =0, toplam =0, gelen =0; for(int i=0; i<worker; i++) MPI_Send(&is, 1, MPI_DOUBLE, i+1, baslik, MPI_COMM_WORLD); is++; while(is<tasks) MPI_Recv(&gelen, 1, MPI_DOUBLE, MPI_ANY_SOURCE, baslik, MPI_COMM_WORLD, &durum); // işlem sonucunu mevcut processten alır. toplam += gelen; MPI_Send(&is, 1, MPI_DOUBLE, durum.mpi_source, baslik, MPI_COMM_WORLD); // yeni iş yollar is++; printf("\npi Sayısı :%.10g\n",toplam); void slaves(int sira) double bas, son, hesaplanan; // aralık bilgisi double gelen=0; while(gelen <tasks) MPI_Recv(&gelen, 1, MPI_DOUBLE, 0,baslik, MPI_COMM_WORLD, &durum); bas = gelen * area; son = bas + area -1; hesaplanan = calculatepi(bas, son, intervals); MPI_Send(&hesaplanan, 1, MPI_DOUBLE, 0, baslik, MPI_COMM_WORLD); 5
Başlangıçta bir aralık ve görev bilgisi belirlenip, her bir paketin boyunun hesaplanması gerekir. (area=interval/tasks) çiftliği modelinin tanımında da belirtildiği gibi, işleri dağıtan ve yöneten bir ana süreç olmalıdır. Yani programda rank=0 olan ana süreç, master süreç olarak belirlenmiştir. İşleri oluşturacak ve mevcut süreçlere başlangıçta ve istek olduğunda işleri dağıtacak olan süreçtir. Her bir worker süreç hesaplama yapacağı aralığı belirler. Kendisi için belirlediği son noktaya gelene dek Pi sayısının ilgili kısmını hesaplar. calculatepi() fonksiyonu her bir aralık için hesaplama yapan alt fonksiyondur. Bu fonksiyon en küçük kareler veya yamuk kuralı olarak bilinen yönteme bağlı kalarak oluşturulmuştur: calculatepi() fonksiyonunda her bir süreç hesapladığı aralığın sonucunu MPI_Send() fonksiyonu ile ana sürece gönderir. Ana süreç ise bu değerleri toplar ve sonuç olarak Pi sayısı elde edilir. Eğer hala yapılacak işler varsa, worker süreç ana süreçten iş isteğinde bulunur. Ana süreç işlerin bittiğinden tüm süreçleri haberdar eder ve program sonlanır. OpenMP kütüphanesini C programlama dilinde kullanabilmek için programa omp.h başlık dosyası eklenmelidir. Bu dosya OpenMP'nin kullandığı gerekli veri türlerini ve çalışma zamanı kütüphane rutinlerini içerir. Aşağıdaki uygulamada, belirli sayıda iterasyona sahip bir döngünün yapacağı işler iş parçacıklarına eşit oranda dağıtıldı ve hesaplanan sonuçlar reduction işlemi ile toplam değişkeninde toplanarak birleştirildi. Uygulama kodları incelenirse; #pragma omp parallel direktifi: Paralel hesaplama yapılacak bir alan oluşturulur. Bu alan içindeki tüm komutlar paralel olarak koşulur. private(i,x) direktifi: For döngüsünde kullanılacak i indis değeri ve ara bir hesaplama değerinin tutulacağı x değişkeni özel (private) olarak tanımlanır. Paralel olarak oluşturulacak her iş parçacığı i ve x değişkenlerini yerel (olarak) oluşturacak ve sadece kendileri kullanacak. reduction(+:toplam) direktifi: Her bir iş parçacığı kendi iterasyon aralığındaki hesaplama değerlerini kendi yerel toplam değişkenlerinde toplar ve tüm iş parçacıkları hesaplamalarını bitirdiklerinde reduction işlemi ile her iş parçacığından gelen toplam değerleri toplanır ve parçalanan görevler birleştirilir. #pragma omp for direktifi: Bu direktif ile döngüdeki toplam iterasyon her iş parçacığına eşit miktarda dağıtılır ve döngünün her parçasının farklı bir iş parçacığı tarafından hesaplanması sağlanır. 6
Uygulamanın paralel hesaplama yapan kod parçası aşağıdaki gibidir: baslangic_z=omp_get_wtime(); #pragma omp parallel private(i,x) reduction(+:toplam) #pragma omp for for(i=0; i<adim_sayisi; i++) x = (i+0.5)*adim_miktari; toplam += 4.0/(1.0 + x * x); bitis_z=omp_get_wtime(); pi=toplam * adim_miktari; 7. Deneye Hazırlık 1. 7. çiftliği modelini ve paralel programlamada nasıl kullanıldığını araştırınız. 2. Herhangi bir integral ifadesi nasıl sayısal ifadeye dönüştürülür? 3. Bir paralel uygulamanın performansını ölçmede kullanılan metriklerden hızlanma ve verimlilik nedir, nasıl hesaplanır ve performans ölçmede nasıl kullanılırlar? Öğreniniz. 4. Grain size ve optimum grain size nedir? Nasıl belirlenir veya hesaplanırlar? 5. MPI üzerinde basit bir paralel programı nasıl koşarsınız öğreniniz. 6. PI sayısını hesaplanmasında kullanılacak bir paralel C programı yazınız. 8. Deney Raporu 1. Hazırladığınız paralel PI sayısı hesaplama programını çalıştırınız ve işlemci sayılarını değiştirerek hızlanma ve verimlilik eğrilerini çiziniz. 2. Aynı programı tek işlemci üzerinde koşunuz ve performansı gözlemleyiniz. 3. Paralel PI sayısı hesaplama programını 7 işlemci ile koşunuz ve grain size değişimine göre hesaplama zamanı eğrisini çiziniz. 4. PI sayısının hesaplanmasında nasıl bir paralel yük dengelemesi tekniği kullanılmıştır? Programı inceleyerek çıkartınız. Deney sorularını cevaplayıp, deney esnasında çizilen hızlanma ve verimlilik eğrilerini de grup adına hazırladığınız rapora ekleyerek en geç sonraki hafta deney saatine kadar yazıcı çıktısı olarak getiriniz. 9. Kaynaklar [1] Barry Wilkinson and Michael Allen, Parallel Programming: Techniques Applications Using Networked Workstations and Parallel Computers, Prentice Hall, 1999. [2] Thomas, Braunl, Parallel Programming; an Introduction, Prentice Hal, 1993. 7