Paralel Programlama Ortamları

advertisement
Paralel Programlama Ortamları
Elis Soylu1, M. Akçay2
1
2
Eskişehir Osmangazi Üniversitesi, Fen Edebiyat Fakültesi Matematik- Bilgisayar Bölümü, Eskişehir
Dumlupınar Üniversitesi, Mühendislik Fakültesi, Bilgisayar Mühendisliği Bölümü,Kütahya
[email protected],
[email protected]
Özet: Bu çalışmada paralel programlama mantığından bahsedilip, bu ortamların karakteristik
özellikleri üzerinde durulacaktır. Okunabilirlik, kısalık, hata kontrolü, sınıf – metot yapıları,
etkinlik, modülerlik ve polimorfizm gibi özellikler incelenecektir. MPI (Message Passing
Interface), Java Thread, CUDA (Compute Unified Device Architecture), OpenMP, PThread ve
Haskell dilleri ile paralel matris çarpımı algoritması üzerinde inceleme yapılacaktır.
Anahtar Sözcükler: Paralel Programlama, Matris Çarpımı, MPI, Java
Thread, CUDA, OpenMP, PThread, Haskell.
Parallel Programming Platforms
Abstract: In this paper, parallel programming’s logic is mentioned and these platforms’
characteristical properties will be given. Readability, brevity, error checking, class-method
structure, effiency, modularity and polymorphism will be investigated. Parallel matrix
multiplication algorithm will be investigated with MPI (Message Passing Interface), Java
Thread, CUDA (Compute Unified Device Architecture), OpenMP, PThreads and Haskell.
Keywords: Parallel Programming, Matrix Multiplication, MPI, Java Thread,
CUDA, OpenMP, PThread, Haskell.
1. Giriş
Bilgisayar
programcıları
programlama
sürecinin başından beri mevcut hesaplamayı
daha da hızlı yapabilmek için büyük çaba
harcamışlardır.
Bu
çaba
özellikle
modellemeler, mühendislik çalışmaları ve
bilimsel hesaplamalarda daha zorunlu hale
gelmiştir.
Bu ihtiyaçlar
ile
paralel
programlama kavramı ortaya çıkmıştır. Paralel
programlama, bir problemin birden fazla
bilgisayar veya işlemci kullanılmasıyla kısa
sürede çözüme ulaşılması için kullanılan bir
yöntemdir.
Paralel programlamanın en temel kilit
noktaları; haberleşme ve senkronizasyondur.
Dolayısıyla bu kilit noktalarıyla birlikte
donanımsal özellikler yazılımsal özellikler ile
uyumlu olarak hareket etmelidir. Birden fazla
işlem biriminin olması, birimlerin kontrolünde
mimarilerine uygun yazılımlara yönelik işler
yapılması gereğini ortaya koyar. Verimli bir
kullanım ile mümkün olan optimal sürede
işlem sonucunu ortaya koymak en temel amaç
olmuştur. Böylece kullanımı kısıtlı olarak
gerçekleştirilen paralel programlama değer
görmeye
başlamıştır.
Ayrıca
Paralel
programlamaya uygun makinelerin de sayısı
artmıştır [1].
Paralel programlama uygulandığı biçimler
bakımından aşağıdaki farklılıkları içerir.


Paralelliğin hangi kısımda yapıldığı
Paralel
program
kısımlarının
tanımlanma şekli
 İşlemcilerin haberleşmesi
 Paralel kısımların eşzamanlı çalışma
prensipleri
Uygulanan metotlar ile süper bilgisayarlar
denilen normal bilgisayarlardan daha kısa
sürede çok fazla veriyle problemin çözümünü
yapan makineler ortaya çıkar [2].
2. İş parçacığı Tabanlı Yöntemler
2.1 Java Thread ile Paralel
Programlama
Thread, bir programın birbirinden
bağımsız işlem parçalarını yürütmekle
görevli en küçük parçasıdır. Kullanıcı
tarafından ve işlemci tarafından oluşturulan
thread’ler olmak üzere iki farklı şekli
vardır. Kullanıldığı yerlere bakılacak
olursa, aynı görev içinde işlemcinin farklı
thread’leri kullanıma koyması paralel
programlamada karşılaşılan kısmıdır.
Birçok programlama dilinde thread
yapıları
kütüphaneler
yardımıyla
oluşturulur. Bu kütüphanelerden kullanılışı
açısından Java Thread uygulama ara
yüzü en basit kullanıma sahip olanıdır. Her
bir Java programı bir işi, main() metodu
ile gerçekleştiren en azından bir thread ile
iş yapar. Thread’ler arası senkronizasyon
ve haberleşme işlerinin dengeli olabilmesi
için mutex, lock, barriers ve
deadlock gibi metotlara ihtiyaç duyulur
[3].
2.2 CUDA ile paralel programlama
Cuda, Nvidia firması tarafından üretilen
grafik işlemci birimi kullanılarak paralel
programlama yapılan mimari çeşididir.
CUDA işlemciyi kullanarak mimari
yardımıyla kernel adı verilen programın
serileştirilmesiyle paralel yapıya ulaşılır
[4].
CUDA, SIMT (Single Instruction Multiple
Thread) paralel programlama modeline
sahiptir. Thread denilen yapılar uygun
sayıda bir araya gelerek warp denilen
yapıları, warp’lar birleşerek blok’ları,
blok’lar birleşerek grid denen yapıları
meydana
getirirler.
Paralel
programlamanın işlemci mimarisiyle en
optimal çalıştığı thread sayısı 32 dir. Bu
sayı dışında olan durumlar için
thread’lerde boşta bekleme (idle)
denilen durum ortaya çıkar.
Thread’ler kendi içlerinde yaptıkları
işlerde birbirlerinden bağımsız hareket
ederler. CPU ile GPU arasındaki
haberleşme birbirinden bağımsız algoritma
parçaları ile haberleşme trafiği az
olacağından daha hızlı çalışır. Örneğin;
birbirinin sonucunu bekleyen seri bir
algoritma parçasından paralellik adına
verimli sonuç almak pek mümkün değildir.
Bu gibi durumlarda bant genişliği,
haberleşme koşullarına bağlı olarak
darboğaz (bottleneck) denilen durumların
oluşması sıklıkla karşılaşılan bir durumdur.
Bu gibi durumların çözümlenmesi için
senkronizasyonun thread’ler arasında
uygun komutlarla sağlanması gerekir [5].
2.3 PThread ile Paralel Programlama
Birçok çok çekirdekli işlemci thread’ler
için bir POSIX standardı olarak bilinen
POSIX
THREAD (PThread) yapısını
kullanır. PThread yapısı, C programlama
dilinin tipleri, fonksiyonları ve sabitlerini
içeren bir kütüphanedir. ‘pthread’ ön eki
kullanılmak üzere yaklaşık 100 civarında
PThread prosedürü bulunmaktadır. Bu
prosedürler 4 ana başlık altında
toplanabilir:




Thread
yönetimi
(thread
oluşturma, birleştirme,…)
Mutex yapıları
Koşul değişkenleri
Senkronizasyon
En çok kullanılan PThread metotları ise;
pthread_create, pthread exit,
pthread cancel, pthread attr
init, pthread attr destroy
şeklindedir [6].
2.4 OpenMP ile Paralel Programlama
OpenMP, shared memory mimarisini C,
C++, Fortran dillerinde destekleyen bir ara
yüzdür. Derleyici komutları, kütüphane
metotları, ortam değişkenleri gibi yapıları
bünyesinde
barındırır.
OpenMP
kütüphanesi taşınabilir bir özellik sunması
açısından
bilgisayarcılar
için
paralelleştirmede önemli bir yöntemdir.
Çoklu iş parçacığı yönetimini sağlar.
Paralel çalıştırılacak kod kısımları thread
yapılarına iş bölümü ile dağıtılır.
Ompgetthreadnum() fonksiyonu ile
her thread kendine özgü işi yapar. Her
thread kendine verilen görevi bitirdikten
sonra yeni bir iş parçası almak için tekrar
kuyruğa girer. İşin tamamı bitene kadar bu
döngü devam eder. Hem görev hem de veri
paralelliği açısından OpenMP önemlidir
[7].
2.5 Haskell ile Paralel Programlama
etmesini sağlayan önemli türevlerinden
biridir [9].
3. Dağıtık Yöntemler
3.1 MPI ile Paralel programlama
MPI (Message Passing Interface), dağıtık
mimarideki
makinelerde
paralel
programlama
yapmayı
kolaylaştıran
fonksiyonlar
kütüphanesidir.
Temel
işleyişi, ayrık adres uzaylarına sahip
işlemciler arasında mesaj alıp - verme
yöntemi şeklindedir.
İşlemciler arasında haberleşmeyi sağlamak
için MPI_COMM_WORLD komutuyla bir
ortam oluşturulur. Bununla birlikte,






MPI_Init
MPI_Finalize
MPI_Comm_Size
MPI_Comm_Rank
MPI_Send
MPI_Receive
Haskell, GHC isimli derleyiciye sahip bir
fonksiyonel programlama dilidir. Çok
çekirdekli mimariler için geniş kütüphane
seçeneğiyle oldukça etkilidir [8].
En sık kullanılan MPI komutlarıdır.
Bir fonksiyonel programlama dili olarak
Haskell, veri bağımsızlığı ile birbirinden
bağımsız fonksiyonlardan oluştuğu için
durum
(state)
değişikliği
gözlenmediğinden paralellik açısından
değerlidir.
Kaynak ‘0’ olarak numaralandırılarak yani
verinin yer aldığı ve dağıtılacağı bilgisayar
numarası verilerek numaralandırma yapılır.
Koşul ifadeleri yardımıyla da bileşen
bilgisayarlara veri dağıtımı mesaj yoluyla
gerçekleşir. Benzer yolla da verilerin
toplanması esnasında mesajlar toplanarak
işlenmiş veri elde edilir [10].
Haskell dili, paralelliği SMP (sharedmemory
multi-processed)
üzerinde
gerçekleştirilir. Thread denilen bağımsız
yapılarla paralel olarak işlemciler üzerinde
istenilen işlemler kolaylıkla gerçekleştirilir.
Parallel isimli ara yüz içinde par ve seq
isimli
iki
fonksiyon
ile
işlem
paralelleştirilir. Eden ve GpH, Haskell
dilinin
kullanıcıya
görev
paralelleştirmesini ve verileri ifade
4. Karakteristik Özellikler
Java gibi nesnel bir dilde ise class yapısı
içinde tip tanımlaması yapılabilir. Java
dilinin önemli bir kısmını aşırı yüklenmiş
metot yapısı oluşturur. Java dili genel
olarak nesnelerle program altyapısını
oluşturur. Hem çalışma sırasında hem de
derleme aşamasında hata kontrolünü
sürekli gerçekleştirir. En önemli özelliği
platformdan bağımsız olmasıdır [11].
Haskell dili, dilin tasarımı gereği metot ile
tip tanımını birbirinden ayırır. Tip sınıfı ile
objenin kullanacağı kurallar belirlenerek bu
tanımlama yapılır. Aşırı yüklenmiş metot
yapısı bu dil tarafından desteklenmez.
Public, Private gibi özellikler Haskell ’de
yer almaz. Bunun yerine bir sınıfın
bileşenleri modül sistemi içinde saklanıp,
açıklanır. Bir fonksiyonel programlama dili
olarak Haskell, polimorfik olması ve yanetkisiz çalışması ile diğer dillerden ayrılır.
Atama deyiminin bulunmayışı beraberinde
değerlerin çakışmamasını yani yan-etki
durumunun ortadan kalkmasını sağlar.
Polimorfizm ile de temel sınıflardan yola
çıkılarak
çeşitli
obje
yapılarının
türetilmesini sağlar [12].
MPI, yapısı gereği hata kontrolünü yapması
ve okunabilirliğinin kolay olması ile açıkça
ifadesi mümkündür. Görev paralelleştirme
metodunu kullanır.
CUDA, mimariye uygun şekilde tekrar
düzeltilebilir yapısı vardır. Class- metot’lar
yardımıyla yeni fonksiyonlar üretebilir ve
kolayca
kullanılabilir.
NVIDIA’nın
tasarladığı Nsight modülü ile hata ve
performans kontrolü açıkça listelenir.
İşlemcilerin dikkatli bir şekilde etkin
kullanımı gerçekleştirilir [13].
PThread, çok işlemcili bir bilgisayarda
birçok thread yapısını aynı anda
çalıştırır.
Thread’ler
birbirini
engellemeyecek düzende iş yapar. Böylece,
çok karmaşık işlemler de kolaylıkla
thread’ler yardımıyla paralelleştirilir.
OpenMp
ise,
taşınabilir
ve
ölçeklendirilebilir
olması
açısından
paralelliğe uygundur.
Bu karakteristik özellikler, matris çarpımı
algoritması ile 1000x1000 tipli bir matriste
performans incelemesini gösteren tablo
aşağıdadır.
Programla
ma Dilleri
OpenMP
Donanım
Süre
Hızlan
ma
3.320x
Intel
3.802s
Core 2
Quad
Java
Intel
8.73s
7x
Thread
Xeon
Dual
Core
CUDA
GeForce
0.25s
2.56x
GTX 280
SC
MPI
Intel
0.111s
5.70x
Core 2
Quad
PThread
80.056s
0.9371
process
x
Sun Ent.
2 GB M.
Haskell
Intel
7.2s
3.8x
Core i-7 6
GB M
Tablo 1- Matris çarpımı algoritması ile
Paralel programlama ortamlarının
performansları
Bu tabloda matris çarpımı algoritması, blok
parçalama yöntemiyle oluşturulmuştur. Bu
algoritmanın karmaşıklığı N, işlemci sayısı
olmak üzere seri olarak O(N), paralel
olarak O(log N) dır.
Elde edilen performanslardan OpenMP
platformu ile 4 kere çalıştırılıp ortalama
süre hesaplanmıştır [14].
Java için, Java Hotspot JIT in Version
1.6.0_13 ortamında test edilmiştir [15].
CUDA platformu ise belirtilen GeForce
işlemcisinde test edilmiştir [16]. MPI ile
elde edilen sonuçlar matristeki blokların
parçalanması yöntemiyle elde edilmiştir
[17]. PThread için diğerlerinden farklı bir
makinede yüksek bir performans elde
edilmiştir [18]. Haskell platformunda GpH
modülü yardımıyla elde edilen her thread
yapısına bir blok karşılık gelecek şekilde
sonuç elde edilmiştir [19].
A., "Paralel Hesaplama ve CUDA", 6th
International Advanced Technologies
Symposium 2011 (IATS'11), June 2011.
[5] Akaydın, B., Tunçel M., “Introduction
to CUDA”, ITU Cuda education, 2013.
5. Sonuç ve Öneriler
MPI, Java Thread, CUDA, Haskell,
PThread,
OpenMP
platformlarının
paralellik ile gösterdiği karakteristiksel
özellikler temel özellikleriyle birlikte
incelenmiştir. MPI ve PThread platformları
paralellik açısından daha gelişmiş bir
ortama sahiptir. Matris çarpımında blok
parçalama
yöntemiyle
incelenen
platformlarda
derlenerek
performanslarındaki farklılıklar gözlenmektedir.
Algoritmaya uygunluğu açısından etkin
seçilen
bir
platform
nanosaniye
derecesinde de olsa daha hızlı sonuç
verebilir.
[6] Prasad J., “Shared Memory
Programming with pthreads”, InterUniversity Centre for Astronomy &
Astrophysics Pune, India 2012.
[7] en.wikipedia.org/wiki/OpenMP [Son
Erişim Tarihi: 18 Aralık 2014].
[8]
https://www.haskell.org/haskellwiki/Hask
ell_for_multicores [Son Erişim Tarihi: 10
Aralık 2014].
[9] Coutts, D., Löh, A., “Modern
Programming languages”, Copublished by
the IEEE CS and the AIP, 12, 1521-9615,
2012.
6. Kaynaklar
[1] Erarslan, G., "Paralel Programlama ve
MPI",
http://seminer.linux.org.tr/wpcontent/uploads/ParalelProgramlamaveMP
I.pdf [Son Erişim Tarihi:13 Aralık 2014].
[2] Ergün, U., Sayar, A., "Fonksiyonel
Programlama
Dilleri
ile
Paralel
Programlama",
Niğde
Üniversitesi
Mühendislik Bilimleri Dergisi, Cilt 3, Sayı
2, 1-17, 2014.
[3] Meyer, B., Pedroni, M., "Concurrent
Programming with Java Threads",
Software
Architecture,
2010,
http://se.inf.ethz.ch/old/teaching/2010S/0050/slides/13_softarch_self_study_thre
ads.pdf [Son Erişim Tarihi: 10 Aralık
2014].
[4] Akcay, M., Sen, B., Orak, I., M., Celik,
[10]
https://computing.llnl.gov/tutorials/mpi
[Son Erişim Tarihi: 11 Aralık 2014].
[11] Çay T., İşcan F., “Harita
Mühendisliğinde Kullanılan Programlama
Dilleri ve Yazılımları”, Akademik
Bilişim’02, 2002.
[12] Sabel, D., Schmidt-Schauß, M.,
“Conservative Concurrency Haskell”, 27th
Annual ACM/IEEE Symposium on Logic
in Computer Science, 2012.
[13] Bhardwaj D., “Parallel Computing”,
Indian Institute of Technology, Delhi –110
016 India, 2002.
[14] Chowdhury, R., “Parallel Computing
with
OpenMP
to
solve
matrix
Multiplication”, UCONN BIOGRID REU
Summer, 2010.
[15] Häuser, J. , “A Test Suite for HighPerformance Parallel Java”, Center for
Advanced Computing Research, 2000.
[16]
Dotzler,
G.,
“JCudaMP:
OpenMP/Java on CUDA”, Programming
Systems Group, 2010.
[17] Quinn, M., “Parallel Programming in
C with MPI and OpenMP”, International
Edition, 2003.
[18]
http://www.cs.cmu.edu/~scandal/papers/sc
98/ [Son Erişim Tarihi: 18 Aralık 2014].
[19] Loidl, H-W., “Comparing Parallel
Functional Languages : Programming and
Performance”, Journal Higher-Order and
Symbolic Computation, Kluwer Academic
Publishers, Volume 16 Issue 3, 203-251,
2003.
Download