Bu site emekli olmuştur. Arşiv amaçlı olarak BT AKADEMİ sponsorluğunda yayın hayatına devam etmektedir.




C#nedir?com
 
YAZAR HAKKINDA
Özkan Eren
Özkan Eren
http://www.csharpnedir.com/
İletişme geçmek için tıklayın.
6 Makalesi yayınlanmakta.
Yazar hakkında detaylı bilgi için tıklayın.
Yayınlanan diğer makaleleri için tıklayın.
İlgili etiketler: disinda fonksiyonu isletim kullanacagim makine makineler makineye mpi_comm_world olusacak output paralel proses siraya verilen vermektedir. C++ / C++.NET Özkan Eren
 
YAZI HAKKINDA
Türü : Makale
Serbest Köşede C#nedir?com üyelerinin hazırladıkları yazılar yayınlanır. Bu yazılar editör incelemesine girmeden yayınlanır.
Seviyesi : Orta
Kategori : C++ / C++.NET
Yayınlanma Tarihi : 29.3.2005
Okunma Sayısı : 50309
Yorum Sayısı : 1     yorum yaz
Site İçi AramaSİTE İÇİ ARAMA
Üye Girişini AçÜye GİRİŞİ
Üye girişi için tıklayın.
Kullanıcı Adı
Şifre
 
Beni her zaman hatırla
Bir hafta boyunca kullanıcı bilgilerinizi kullanıcı çıkışı yapana kadar hatırlar. (Paylaşılan bilgisayarlarda önerilmez.)
 
Şifremi / Kullanıcı Adımı unuttum.
 
.net TV RSS Serbest KÖŞE (?)
Serbest Köşede C#nedir?com üyelerinin hazırladıkları yazılar yayınlanır. Bu yazılar editör incelemesine girmeden yayınlanır.
emre TAŞ
Silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
Makale Gönder Bende Yazmak İstiyorum
.net TV RSSBlogroll
Turhal Temizer
Conda install environment.yml Package 21.11.2024
Turhal Temizer
Mac OS/X Removing CUDA 21.11.2024
Burak Selim Şenyurt
Rust ile ECS Yaklaşımını Anlamak 21.11.2024
Burak Selim Şenyurt
Birlikte Rust Öğrenelim Serisi 21.11.2024
  Diğer Herşey
Sponsorlar
BT Akademi
Medya Portakal
Video Hosting Sponsoru
Csharpnedir.com bir Ineta üyesidir
Uzman Abi
Her Yönüyle C# - Sefer Algan
MPI ile Paralel Programlama - 1 
 
Kapat
Sayfayı Yazdır Sık Kullanılanlara Ekle Arkadaşıma Gönder MySpace Del.Ico.Us Digg Facebook Google Mixx Reddit StumbleUpon
Paralel programlamayı herkes duymuştur ama çok az insan kullanmıştır. Paralel programlamanın az kullanılmasının sebebi paralel makinelerin pahalı olması kontrolünün zor olması ve en önemlisi de genel olarak ihtiyacımızın olmamasıdır. Peki paralel hesaplamalar nerede kullanılmaktadır? Araştırma laboratuarları, üniversiteler, ileri teknoloji kullanan şirketler limitlerinin zorlandığı durumlarda paralel makinelere ihtiyaç duymaktadırlar. Örnek olarak Koç Üniversitesinde “moleküler simülasyonlar”, “quantum computing”, ”computational electromagnetics”, ”bioinformatics” ve benim de uğraştığım “computational flow simulation/modelling” gibi değişik araştırma projeleri üzerinde uğraşılmaktadır. Bu paralel hesaplamalar için de MPI adı verilen Message Passing Interface adlı paralel işlem kütüphanelerini (Library) kullanmaktayız. Bunun dışında değişik kütüphaneler de vardır.

Donanım / Yazılım  

Donanım olarak en basit makineleri birbirine bağlayarak bile bir cluster elde edebilirsiniz. Bunun için bilgisayarınıza gerekli MPI (Message Passing Interface – Paralel kütüphaneler başka standartlar da var ben MPI kullanıyorum) dosyalarını ve bazı programları kurmanız gerekmektedir. Bunlardan bir tanesi openPBS (Open Portable Batch System ) iş akışını düzenlemektedir ve OSCAR adlı ( MPI,SSH,SSL,MPICH,... gibi gerekli kütüphaneleri, programları bize sağlamaktadır ) programdır. Her ne kadar işletim sistemi olarak unix/linux tabanlı işletim sistemleri desteklense de windows tabanlı işletim sistemleri için de bu yazılımların versiyonları vardır. Donanım olarak bütün işlemciler desteklenmektedir (Windows işletim sistemlerinde bu destek yoktur). Ayrıca ULAKBIM den (128 node’ luk güzel bir clusterları var) account almanız mümkün, tabi akademik amaçlar için kullanacağınıza ikna etmeniz gerekecektir. Yine de account alamaz ve test etmek istediğiniz bir kod olursa bana yollarsanız ben deneyebilirim.

MPI nedir? 

Kısaca bahsettik ama MPI nedir? Nasıl çalışır? Başka makinelere/cpu’ lara nasıl sonuç yollar... Biraz bunlardan bahsedelim. Öncelikle yazdığınız her paralel kodun başına “mpi.h” headerini eklemeniz gerekmektedir. Bu header dışında kullanmanız gereken başka header yoktur. MPI fonksiyonları makineler arası iletişimi, işlem önceliklerini, yük ayarını vs düzenlemektedir.Format olarak MPI fonksiyonları MPI_Xxxxx(parameter, ... ) formatını kullanmaktadır. MPI fonksiyonlarını size kısaca tanıtayım:

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.

Yukarıda gördüğünüz fonksiyonlar genel MPI fonksiyonlarıdır ve sadece kodunuzu yönetmek amacıyla kullanılmaktadır. Bunların dışında 100’ e yakın daha fonksiyon vardır. Onlara gelecek yazılarımızda değinmeye çalışacağız.

Hello World 0 Hello World 1 Hello World 2  ....  

Şimdi geldik kod kısmına! Klasikleşmiş “merhaba dünya” örneğimizi bu sefer paralel bilgisayarlarda uygulayacağız. Her bilgisayardan selamlama mesajı göndereceğiz. Bunun için yukarıda açıkladığımız fonksiyonları kullanacağız.

#include <stdio.h>
#include "mpi.h"
int main( argc, argv )
int  argc;
char **argv;
{
    int rank, size;
    MPI_Init( &argc, &argv );
    MPI_Comm_size( MPI_COMM_WORLD, &size );
    MPI_Comm_rank( MPI_COMM_WORLD, &rank );
    // beklemek istemediğim için fprintf komutu ile myout.dat dosyasına yazdırıyorum
    printf( “Hello world from process %d of %d \n", rank,size);
    MPI_Finalize();
    return 0;
}

Compile edip çalıştırınca cevap olarak aşağıdaki ekranı görmekteyiz.



Haklı olarak “sadece bir tane proses gözüküyor” diyeceksiniz. Hatamız burada paralel işlem yapacak bir kodu normal bir C kodunu çalıştırdığımız gibi çalıştırmamızdır. Bunun için paralel makineye iş yüklemek gerekmektedir (işin bu kısmı genelde hiç söylenmez). Bunun için PBS yazılımının manuelinden nasıl komut aldığına bakıyoruz (scriptteki #PBS bu bahsettiğimiz komutlardır). Örnek olarak yüklediğimiz işe isim vermek istersek #PBS –N benim işim diyebiliyoruz. Oluşacak output ve error bilgileri için log dosyaları da oluşturabiliriz. Daha sonra bu yazdığımız 10-15 komutu bir defada çalıştırmak için bir “job script” yazıyoruz. Bu yazıda amacımız linux öğretmek olmadığı için bunları detaylı olarak açıklamayacağım. Yukarıda bahsettiğim PBS adlı program sizin verdiğiniz komutları değerlendirerek bilgisayarların iş yoğunluğuna göre verilen işleri sıraya sokmaktadır ve ona göre cpu, hard disk, memory tahsisi yapmaktadır. Size bu iş için yazdığım “job scripti” göstereyim. Aşağıda gördüğünüz ### comment yani yorumlar, geri kalan kısımlar execute edilecek komutlardır.Yazımın sonunda size daha kestirme bir yoldan da bahsedeceğim ama o yöntem sistem admini tarafından görülürse hiç hoş karşılanmayan bir durumdur (ki genelde serverlerde sizin ana makineye PBS aracılığı ile iş yüklemeniz dışında kolay kolay komut kullanamazsınız).

#!/bin/sh
### iş ismi “ozkanen” ismi verdim
#PBS -N ozkanen
### Output files
### olusacak output ve olusacak error loglarını  buraya koyabiliriz
#PBS -o ozkanen.out
#PBS -e ozkanen.err
### Buraya dikkat edin!!!
### 4 gördüğünüz kısım 4 makine kullanacağım demek
### 1 gördüğünüz kısım 1 makinede 1 işlemci kullanacağım demek (hattusas da her node da bir işlemci var)
#PBS -l nodes=4:ppn=1
### programın ne kadar çalışacağını söylemektedir
#PBS -l cput=32:00:00
#PBS -l walltime=32:00:00
### Queue name
### clusteri paralel olarak kullanacagim icin asagidaki kodu yazıyorum
### clusterları isterseniz tek tek de kullanabilirsiniz
#PBS -q parallel
#PBS -m abe
### cevap cıkınca bana mail at demek oluyor aşağıda
#PBS -M [email protected]
### Script Commands
### aşağı kısımlar o kadar önemli değil sadece size işlerin çalıştığını ve nerede çalıştığını size söylüyor
cd $PBS_O_WORKDIR
echo "Running test"
echo ’group main’ > machines
cat $PBS_NODEFILE | awk ’{print "host " $1}’ >> machines
echo ’current directory is’
pwd
echo ’Running test’
### aşağıda ./hello adını verdiğimiz dosyayı çalıştırıyoruz
### istersek cevapları output dosyamıza yazdırabiliriz
./hello   out
### işimiz bittiği zaman bize bittiğini haber vermektedir
echo "job complete"
exit 0

Bu job scripti yazdıktan sonra oerentest.job ismi ile kaydediyorum. Çalıştırmak için de qsub oerentest.job diyorum.



“a” komutu yazdığım zaman ekranda 91621 kodu ile işimin sisteme girildiğini görüyorum. Status anlamına gelen “S” sütunundan yüklediğim işimin Q (yani sırada olduğunu) durumunda olduğunu görüyorum. Kodum saniyelik bir run yapıp bana cevap verecek ama yukarıda gördüğünüz gibi sıra olduğu için PBS sıraya sokuyor (32 node da olsa her zaman fazla iş var). Eğer dikkatlice bakarsanız NDS de “4” yazdığını görürsünüz bu “4” tane makine istiyorum anlamındadır, ayrıca ben dahil kimse memory’ den kısıtlama yapmadığı için Req memory kısmı boş gözükmektedir. Ayrıca Req Time sütununa  bakarsanız 32 saatlik bir iş verdiğimi ve Elap Time sütununa bakarsanız hiç çalışmadığını göreceksiniz. Bayağı uzun sürdüğü için ben bu işimi bir output dosyama yazdırıp sonraya bırakıyorum ve filmimi seyrediyorum. Aradan bayağı bir zaman geçtikten sonra sıradakilerin işi bitip benim işim de çalışınca sabırsızca beklediğim “mydat.out” dosyam oluşuyor. VI editörü ile mydat.out dosyasına bakarsak :



Beklediğimiz sonucu görüyoruz. Şimdi kodumuza tekrar dönelim. Temel bir C kullanıcısına yabancı gelen aşağıdaki satırlara bakalım:

// verilen proseslerin toplam sayısını bize size olarak dönmektedir
MPI_Comm_size( MPI_COMM_WORLD, &size );
// prosesin hangi bilgisayarda çalıştığı rank olarak dönmektedir
MPI_Comm_rank( MPI_COMM_WORLD, &rank );
// sonuçları print ediyoruz
printf( “Hello world from process %d of %d \n", rank,size);

Yabancı fonksiyonlardan ilki olan Comm_size fonksiyonunu çağırıyoruz.

MPI_Comm_size( MPI_COMM_WORLD, &size );

Yukarıda da bahsettiğim gibi MPI_Comm_size fonksiyonu bize paralel makineye yüklediğimiz işin kaç bilgisayar tarafından çalıştırılacağını “size”  değeri ile vermektedir. MPI_COMM_WORLD değişkeni ise çalıştığımız environmenti (çevre) vermekteyiz. Makinemiz bunu default çalışma parametresi almaktadır. Şimdi elimizde size değeri 4 makineye iş yüklediğimiz için 4 olarak bize dönmektedir. Sırada rank fonksiyonumuz var!

MPI_Comm_rank( MPI_COMM_WORLD, &rank );

Rank fonksiyonu bize proseslerin MPI tarafından sıraya sokulduktan sonra hangi sırada olduğunu rank ile bize dönmektedir. En başta ki MPI_COMM_WORLD değerini de size fonksiyonunda olduğu gibi default olarak giriyoruz. MPI tarafından sıraya biz herhangi bir tanımlama yapmadığımız için ( prosesleri sıraya sokmak için ve bunların arasında etkileşimlere göre sıra önceliği tanımlayabileceğimiz fonksiyonlar vardır. Bunlar arasında MPI_Send, MPI_Recv, MPI_Ssend, MPI_Bsend, MPI_Buffer_attach, MPI_Rsend fonksiyonlarını sayabilirim bunları gelecek yazımda detaylı olarak anlatacağım ve örnek kodla açıklayacağım. Örnek olarak MPI_Recv fonksiyonu bir bilgisayardan mesaj aldığı zaman o mesajı gerçekleştirene kadar beklemektedir (eğer bunu kullanmazsak bir makinenin oluşturmadığı verilere ulaşmaya çalışmak hata döndürürdü).

Kolay Yötem : Job Script yazmadan çalıştırmak

Yazıma girişte size bu job scripti yazmadan daha kolay bir şekilde bu programı çalıştırabileceğimizi söylemiştim (yine açıklayayım çoğu clusterlar buna izin vermemektedir ,PBS ve benzeri uygulamalar üzerinden programlar çalıştırılmaktadır). Şimdi gelelim kolay yönteme! Komut satırına “mpirun –np 3 hello” yazıyoruz. Bunun anlamı şudur “Bana 3 tane makine kullanarak hello uygulamasını çalıştır”. Bu satırı yazdıktan sonra MPI aktif hale geliyor biz iş sırasını düzenlemediğimiz için MPI hangi prosesten önce cevap gelirse onları sıraya sokarak ekrana cevapları döndürüyor. Komutta eğer 3 yerine 12 yazarsak 12 node kullanarak çalıştırıyoruz. Gördüğünüz gibi her defasında ayrı bir sıra oluşuyor hangi işlemci daha hızlı cevabı gönderirse onun prosesi daha önce gözüküyor.



Gelecek Yazıda  

Gelecek yazıda MPI haberleşme fonksiyonlarını anlatacağım ve bu fonksiyonları kullanarak biraz daha ileri bir örnek çözeceğim (matris çarpımı yapabilirim) ve paralel makineler kullanarak bu örneğin ne kadar hızlı çözülebileceğini göstereceğim.Esenlikle kalın!

Özkan Eren
[email protected]

Makale:
MPI ile Paralel Programlama - 1  C++ ve C++.NET dili Özkan Eren
  • Yazılan Yorumlar
  • Yorum Yaz
TEM
15
2016
Emeğiniz için teşekkür ederim.
Sayfalar : 1 
Yorum yazabilmek için üye girişi yapmalısınız. Üye girişi için tıklayın.
Üye değilseniz Üyel Ol linkine tıklayarak üyeliğinizi hemen başlatabilirisniz.
 
  • Bu Konuda Son 10
  • Eklenen Son 10
  • Bu Konuda Geçmiş 10
Bu Konuda Yazılmış Yazılmış 10 Makale Yükleniyor
Son Eklenen 10 Makale Yükleniyor
Bu Konuda Yazılmış Geçmiş Makaleler Yükleniyor