8
KUDA: GPU Hızlandırılmış Ayrık Yarış Durumu Denetleyici Ü. Can Bekar 1 , Tayfun Elmas 2 , Semih Okur 3 , Serdar Taşıran 1 1. Bilgisayar Mühendisliği Bölümü Koç Üniversitesi {ucbekar, stasiran} @ku.edu.tr 2. Bilgisayar Mühendisliği Bölümü University of California, Berkeley, USA [email protected] 3. Bilgisayar Mühendisliği Bölümü University of Illinois at Urbana-Champaign, USA [email protected] Özetçe Bu bildiride özgün bir çalışma zamanı doğrulama çerçevesini sunuyoruz. Yaklaşımımızdaki ana amaç, geleneksel yarış durumu denetleyicilerindeki işletim yüklerini ayırıp, bilgisayarlarımızda bulunan donanımsal olanakları kullanarak, halihazırdaki çalışma zamanına koşut çalışan, koşutlu doğrulama yapmaktır. Bu yüzden çerçevemizi çok çekirdekli işlemcilere (CPU) ve grafik işlemcisine (GPU) sahip kişisel bilgisayarlara herhangi bir donanım eklemesi gerekmeksizin gerçekleştirdik. Çalışmamızdaki ana yenilik, koşutzamanlı bir programın güvenilirlik özelliklerinin grafik işlemcideki iş parçacıklarında denetlenmesinin ilk olarak öne sürülmesi ve bunun için gerekli tekniklerin ve algoritmaların tasarlanmasıdır. Daha önce bu denetlemenin tamamı merkezi işlem ünitesi üzerinde gerçekleşmekteydi, ve denetleyicinin iş parçacıklarının denetlenen programın iş parçacıklarıyla aynı işlemci üzerinde koşması programın başarımını önemli ölçüde şürmekteydi. Denetleyicilerdeki işletim yükünü ikiye ayırıyoruz: (i) gözlemleme ve (ii) denetleme yükleri. Detaylı inceleyeceğimiz bu yazılım çerçevesi, ayırdığımız iki işletim yükünü farklı işlemcilere paylaştırmaktadır. Sonuç olarak, denetlenen koşutzamanlı programın başarımı, yalnızca gözlemleme ve bu gözlemin öteki işlemciye aktarımından kaynaklanan işletim yüklerinden dolayı etkilenir. Bazı ek donanım destekleriyle gözlemleme yükünü hafifleten benzer çalışmalar da literatürde bulunmaktadır. Sunacağımız çerçevenin ön ürünü olan KUDA birimlerimizle yaptığımız deneylerimiz, farklı işlemcideki iş parçalarında koşut zamanda yarış durumlarını (data race) denetlemek, denetlenen koşutzamanlı program ile çok yakın zamanlı (birkaç milisaniye mertebesinde gecikmeyle) çalışğını göstermektedir. Bu sonuç ile, çerçevemizin yarış durumlarını denetlemekten de öte, hatadan geri dönmek için kullanılabilmesinin mümkün olduğunu anlıyoruz. KUDA’da henüz yarış durumlarına odaklandık, ancak ileride koşut zamanlı programların diğer koşut zaman hataları ve bellek hataları gibi farklı güvenilirlik özelliklerini de denetlemesini sağlayabiliriz. Çerçevemizde merkezi işlem ünitesinde çalışan koşut zamanlı programın gözlenmesi ile iş parçacıklarından toplanan çalışma izi bloklamayan bir veri yapısında biriktirilip grafik işlemcisine aktaran bir iş parçası çalıştırıp, çok sayıda görüntü işlemcisi çekirdeği kullanan koşut zamanlı denetleme birimlerimizde denetliyoruz. KUDA, koşutzamanlı çalışan 2 popüler denektaşı takımlarındaki tüm uygulamalarda yaşanmakta olan başarım kaybını (yalnızca bir denektaşı programı hariç tutulması kaydıyla) en az 3 kat azaltmaktadır. 1. Giriş 10-15 yıl öncesine kadar belirli kullanım alanlarının dışında pek rastlanamayan koşutzamanlı programlar, donanım bazlı teknolojik ilerlemelerin fiziksel sınırlara ulaşması ve bilişim sektörünün süregelen taleplerini zorlamaya başlamasından kaynaklanan başarım problemlerine cevaben kısa sürede yaygınlaşştır. Günümüzde koşutzamanlı (concurrent) programlar artık her alanda karşımıza çıkmaktadır. Fakat koşutzamanlı programların uzun süre kısıtlı alanlarda (örneğin işletim sistemi çekirdekleri) kullanılıp uygulama programları pazarına çıkmamasının çok geçerli bir sebebi vardı. Koşutzamanlı çalışmaya özgü hatalardan arınmış koşutzamanlı programlar yazmak zordu. Bu hatalardan en çok karşımıza çıkanı yarış durumlarıdır (data race). Bazı çok özel durumlar hariç, genelde bütün yarış durumları, programlayıcının niyeti dışında oluşur. Bir programın iş parçacıkları (thread), çalışğı işletim sisteminin zaman planı uygulayıcısının (scheduler) farklı çalışma zamanlarında farklı sıralamalar uygulamasından ötürü koşutzamanlı hatalar, sıralı programlardaki hataların aksine, tekrar ettirilip sebebi bulunsa dahi ayıklanması oldukça güç hatalardır. Koşutzamanlı programların güvenilirliğini doğrulamanın bir yolu yarış durumlarını dinamik denetlemektir. Dinamik denetleyiciler yalnızca çalışma zamanında oluşan hataları denetleyebilir. Yarış durumu, çalışma zamanında iki veya daha çok iş parçacığının tek bir bellek konumuna, en az bir yazma işlemi yapmaları ve bu işlemlerin sırasının hata oluşmayacak şekilde zamanlanmamış olmasından dolayı oluşur. Günümüzde yaygın olarak kullanılan, ticari dinamik yarış durumu denetleyicilerinin çalışmakta olan koşutzamanlı programların başarımına etkisinin 300 kat yavaşlamalara kadar erişmesi beklenmedik bir durum değildir. Bizim yaklaşımımızdaki ana amaç, geleneksel yarış durumu denetleyicilerindeki işletim yüklerini ikiye ayırıp, ana işlemcide çalışan programı gözlemlerken bilgisayarlarımızda bulunan grafik işlemcisinde (GPU veya GİB) yarış durumlarını denetlemektir. Bu amacın temelinde iki hedefimiz vardı: (i) denetlenen programın iş parçacıklarının başarımını asgari etkilemesi ve (ii) denetleme birimlerimizin denetlenen programla eş hızlarda çalışması, yani aradaki oluşan farkın tahammül edilebilir olması. İlk hedefimizin temelinde, öne sürdüğümüz yaklaşımımızın modern denetleyicilere nazaran daha verimli bir çerçeve olduğunu özel donanım desteği kullanmadan olduğunu göstermek; ikinci hedefin temelinde ise, çerçevemizin sadece yarış durumlarını denetlemekten de öte, hatadan geri dönme için kullanılabilmesinin mümkün olduğunu göstermiş olmaktır. Eğer ikinci hedefimiz hiç olmasaydı, toplanacak olan çalışma izinin birikmesine izin verip, program sonlandıktan sonra grafik işlemcisine

KUDA: GPU Hızlandırılmış Ayrık Yarış Durumu Denetleyici

Embed Size (px)

Citation preview

Page 1: KUDA: GPU Hızlandırılmış Ayrık Yarış Durumu Denetleyici

KUDA: GPU Hızlandırılmış Ayrık Yarış Durumu Denetleyici

Ü. Can Bekar1, Tayfun Elmas2, Semih Okur3, Serdar Taşıran1

1. Bilgisayar Mühendisliği Bölümü Koç Üniversitesi

{ucbekar, stasiran} @ku.edu.tr

2. Bilgisayar Mühendisliği Bölümü University of California,

Berkeley, USA [email protected]

3. Bilgisayar Mühendisliği Bölümü University of Illinois at

Urbana-Champaign, USA [email protected]

4. Bilişim Enstitüsü EFG Üniversitesi

[email protected]

5. Bilişim Enstitüsü EFG Üniversitesi

[email protected]

Özetçe

Bu bildiride özgün bir çalışma zamanı doğrulama çerçevesini sunuyoruz. Yaklaşımımızdaki ana amaç, geleneksel yarış durumu denetleyicilerindeki işletim yüklerini ayırıp, bilgisayarlarımızda bulunan donanımsal olanakları kullanarak, halihazırdaki çalışma zamanına koşut çalışan, koşutlu doğrulama yapmaktır. Bu yüzden çerçevemizi çok çekirdekli işlemcilere (CPU) ve grafik işlemcisine (GPU) sahip kişisel bilgisayarlara herhangi bir donanım eklemesi gerekmeksizin gerçekleştirdik. Çalışmamızdaki ana yenilik, koşutzamanlı bir programın güvenilirlik özelliklerinin grafik işlemcideki iş parçacıklarında denetlenmesinin ilk olarak öne sürülmesi ve bunun için gerekli tekniklerin ve algoritmaların tasarlanmasıdır. Daha önce bu denetlemenin tamamı merkezi işlem ünitesi üzerinde gerçekleşmekteydi, ve denetleyicinin iş parçacıklarının denetlenen programın iş parçacıklarıyla aynı işlemci üzerinde koşması programın başarımını önemli ölçüde düşürmekteydi. Denetleyicilerdeki işletim yükünü ikiye ayırıyoruz: (i) gözlemleme ve (ii) denetleme yükleri. Detaylı inceleyeceğimiz bu yazılım çerçevesi, ayırdığımız iki işletim yükünü farklı işlemcilere paylaştırmaktadır. Sonuç olarak, denetlenen koşutzamanlı programın başarımı, yalnızca gözlemleme ve bu gözlemin öteki işlemciye aktarımından kaynaklanan işletim yüklerinden dolayı etkilenir. Bazı ek donanım destekleriyle gözlemleme yükünü hafifleten benzer çalışmalar da literatürde bulunmaktadır. Sunacağımız çerçevenin ön ürünü olan KUDA birimlerimizle yaptığımız deneylerimiz, farklı işlemcideki iş parçalarında koşut zamanda yarış durumlarını (data race) denetlemek, denetlenen koşutzamanlı program ile çok yakın zamanlı (birkaç milisaniye mertebesinde gecikmeyle) çalıştığını göstermektedir. Bu sonuç ile, çerçevemizin yarış durumlarını denetlemekten de öte, hatadan geri dönmek için kullanılabilmesinin mümkün olduğunu anlıyoruz. KUDA’da henüz yarış durumlarına odaklandık, ancak ileride koşut zamanlı programların diğer koşut zaman hataları ve bellek hataları gibi farklı güvenilirlik özelliklerini de denetlemesini sağlayabiliriz. Çerçevemizde merkezi işlem ünitesinde çalışan koşut zamanlı programın gözlenmesi ile iş parçacıklarından toplanan çalışma izi bloklamayan bir veri yapısında biriktirilip grafik işlemcisine aktaran bir iş parçası çalıştırıp, çok sayıda görüntü işlemcisi çekirdeği kullanan koşut zamanlı denetleme birimlerimizde denetliyoruz. KUDA, koşutzamanlı çalışan 2 popüler denektaşı takımlarındaki tüm uygulamalarda yaşanmakta olan başarım kaybını (yalnızca bir denektaşı programı hariç tutulması kaydıyla) en az 3 kat azaltmaktadır.

1. Giriş 10-15 yıl öncesine kadar belirli kullanım alanlarının dışında pek rastlanamayan koşutzamanlı programlar, donanım bazlı teknolojik ilerlemelerin fiziksel sınırlara ulaşması ve bilişim sektörünün süregelen taleplerini zorlamaya başlamasından kaynaklanan başarım problemlerine cevaben kısa sürede yaygınlaşmıştır. Günümüzde koşutzamanlı (concurrent) programlar artık her alanda karşımıza çıkmaktadır. Fakat koşutzamanlı programların uzun süre kısıtlı alanlarda (örneğin işletim sistemi çekirdekleri) kullanılıp uygulama programları pazarına çıkmamasının çok geçerli bir sebebi vardı. Koşutzamanlı çalışmaya özgü hatalardan arınmış koşutzamanlı programlar yazmak zordu. Bu hatalardan en çok karşımıza çıkanı yarış durumlarıdır (data race). Bazı çok özel durumlar hariç, genelde bütün yarış durumları, programlayıcının niyeti dışında oluşur. Bir programın iş parçacıkları (thread), çalıştığı işletim sisteminin zaman planı uygulayıcısının (scheduler) farklı çalışma zamanlarında farklı sıralamalar uygulamasından ötürü koşutzamanlı hatalar, sıralı programlardaki hataların aksine, tekrar ettirilip sebebi bulunsa dahi ayıklanması oldukça güç hatalardır.

Koşutzamanlı programların güvenilirliğini doğrulamanın bir yolu yarış durumlarını dinamik denetlemektir. Dinamik denetleyiciler yalnızca çalışma zamanında oluşan hataları denetleyebilir. Yarış durumu, çalışma zamanında iki veya daha çok iş parçacığının tek bir bellek konumuna, en az bir yazma işlemi yapmaları ve bu işlemlerin sırasının hata oluşmayacak şekilde zamanlanmamış olmasından dolayı oluşur. Günümüzde yaygın olarak kullanılan, ticari dinamik yarış durumu denetleyicilerinin çalışmakta olan koşutzamanlı programların başarımına etkisinin 300 kat yavaşlamalara kadar erişmesi beklenmedik bir durum değildir. Bizim yaklaşımımızdaki ana amaç, geleneksel yarış durumu denetleyicilerindeki işletim yüklerini ikiye ayırıp, ana işlemcide çalışan programı gözlemlerken bilgisayarlarımızda bulunan grafik işlemcisinde (GPU veya GİB) yarış durumlarını denetlemektir. Bu amacın temelinde iki hedefimiz vardı: (i) denetlenen programın iş parçacıklarının başarımını asgari etkilemesi ve (ii) denetleme birimlerimizin denetlenen programla eş hızlarda çalışması, yani aradaki oluşan farkın tahammül edilebilir olması. İlk hedefimizin temelinde, öne sürdüğümüz yaklaşımımızın modern denetleyicilere nazaran daha verimli bir çerçeve olduğunu özel donanım desteği kullanmadan olduğunu göstermek; ikinci hedefin temelinde ise, çerçevemizin sadece yarış durumlarını denetlemekten de öte, hatadan geri dönme için kullanılabilmesinin mümkün olduğunu göstermiş olmaktır. Eğer ikinci hedefimiz hiç olmasaydı, toplanacak olan çalışma izinin birikmesine izin verip, program sonlandıktan sonra grafik işlemcisine

Page 2: KUDA: GPU Hızlandırılmış Ayrık Yarış Durumu Denetleyici

yollayabilirdik; yani ikinci hedefimizi tutturmak için yapmamız gereken bu çalışma izinin birikmesini beklemeden işleme alabilmektir.

Çerçevemizde denetlenen program ve denetleme programları farklı işlemci ve iş parçalarında çalışmaktadır. İki program birbiriyle paylaşımlı bellek ve mesajlaşma ile haberleşmektedir. Denetlenecek program sunduğumuz programlama arayüzünü kullanarak dinamik olarak çerçevemize özel gözlemleme fonksiyonlarını çağırır. Bunun için program kodu Pin gibi araçlar kullanılarak çalışma sırasında dinamik olarak değiştirilir. Gözlemleme fonksiyonlarımız içinde çalışma izlerini oluşturan olayların iletişimini sağlayan fonksiyonlar bulunur. Dolayısıyla gözlemleme fonksiyonlarıyla donatılan iş parçacıkları aynı zamanda gözlemlenecek olayları bloklamayan (nonblocking) veri yapısına koymakla yükümlüdür. İşlenenecek olayların birikimini asgariye indirebilmek için bu çalışma izlerini bloklara bölüp, çerçeve dediğimiz sabit uzunluktaki parçalarda denetleme yapıyoruz. Bu çerçeveler sırayla grafik işlemcisine aktarılıp olabildiğince koşutlu olarak denetleyici birimlerde, birbirlerinden bağımsız olarak kullanılır. Çerçevelerin birbirlerinden bağımsız olarak denetlenmesi, denetlememizin doğruluğunun (tüm hataları yakalayabilmesi) çerçevelerin uzunluğuyla ters orantılı olarak etkilenmesi riskini doğurmaktadır. Ancak denemelerimizde kullandığımız uzunluktaki çerçevelerde denetleme doğruluğunun düşmediği görülmektedir. Böylece modern yarış denetleyicilerin aksine, denetleme ve gözlemleme işletim yüklerinin ayrık ve koşutlu olması, denetlenen programın başarımının artarken denetimin hatalara hassasiyetinden feragat edilmesine ihtiyaç duyulmadığı anlamına gelmektedir.

Modern denetleme programları, geleneksel olanlara nazaran, oldukça karmaşık olabilir, ancak bu işlem yükü başka bir işlemciye yüklendiğinden denetlenen programın başarımı daha fazla etkilenmemiş olur. Bu konuda yapılabilecek önemli bir gözlem, gözlemleme ve iletişim işletim yüklerinin özel donanım desteğiyle beraber göz ardı edilebilir mertebelere indirilebileceğidir [1].

Gösterge olması açısından geleneksel Eraser [2] ile modern Goldilocks [3] algoritmalarını çerçevemize uyarladık. Şaşırtıcı olarak, şimdiye dek kullanıcıların sıralı olarak (sequential) olarak çalıştırdığı bu algoritmaların grafik işlemcilerde çalıştırılan koşutzamanlı varyasyonları eskiden olduğundan daha basit bir hal aldı. Bunun sebebi çerçevelerin birbirinden bağımsız olması, dolayısıyla her denetleyicinin birbiriyle haberleşmeye veya eşzamanlı çalışmasına ihtiyaç duymamasıydı. Her denetleyici birim işlediği çerçeveye ayırdığı belleği çerçeveyi denetledikten sonra geri kullandığından bellek işletimine ve karmaşık veri yapılarının paylaşılmasına gerek kalmamıştır.

Bu çerçeveyi Kuda adını verdiğimiz bir araçla gerçekleştirdik. Kuda aracı açık kaynaklı olup http://kuda.codeplex.com bağlantısında herkesin kullanımına açıktır. Koşutzamanlı programları dinamik olarak gözlemek için Pin [4] kütüphanesini kullanıyoruz, gözleme fonksiyonlarımız birer Pin aracı olarak gerçekleştirilmiştir. Denetleme birimlerimiz ise CUDA [5] kütüphanesiyle NVIDIA CUDA-destekli grafik işlemcilerde çalışmaktadır. Deneylerimizde denetlediğimiz koşutzamanlı program olarak PARSEC [6] ve SPLASH-2 [7] denektaşı program takımlarını kullandık. Denetleyici olarak Eraser ve Goldilocks yarış durumu tespit algoritmalarını seçtik, çünkü Eraser denetleyicisi basit ancak kesin (precise) olmayan, Goldilocks ise tam aksine kesinlik sunan ancak karmaşık olan bir

denetleyicidir. Deneylerimizde iki ayrı yaklaşımı daha karşılaştırdık: (i) geleneksel yolla, yani denetlenen programla aynı merkezi işlemcide ve iş parçacıklarında çalışan Eraser denetleyicisi ve (ii) çerçevemiz kapsamında farklı işlemcide çalışan Goldilocks denetleyicisi.

2. Çalışma zamanı gözlemlemedeki zorluklar Bu bölümün amacı çalışma zamanında durum denetleyicilerinin tasarımındaki, özellikle koşutzamandan (concurrency) kaynaklanan başlıca zorlukları göstermektir. Bu zorlukları en kolay şekilde gösterebilmek için öncelikle meşhur ve basit bir yarış durumu denetleyicisini tanıtacağız.

2.1. Eraser yarış durumu denetleyici algoritması

Eraser yaygın kullanılan bir kilit kümesi (lockset) tabanlı dinamik yarış durumu denetleme algoritmasıdır. Bu bölümde anlatımı basitleştirmek için kilit kümelerinin elemanlarını okuma ve yazma diye ayırt etmeyeceğiz.

Yarış durumu, iki veya daha çok iş parçacığının (thread) tek bir bellek konumuna, en az bir yazma işlemi olmak üzere ulaşmaları ve bu işlemlerin sırasının hata oluşmayacak şekilde zamanlanmamış olmasından dolayı oluşur. Eraser ise bu durumu denetleyebilmek için program süresince paylaşılan her değişken x için ortak bir kilit zorlamaktadır.

Eraser algoritması çalışma zamanında paylaşılan her x değişkeninin korunuyor gözüktüğü tüm kilitleri LS(x) adında kilit kümesi ve ayrıca her t iş parçacığının o an içinde tutmakta olduğu kilitler için de LH(t) kilit kümesini tutar. Yani LH(t) kümeleri yalnızca t iş parçacığının bir kilidi açması veya kapamasıyla güncellenir. Algoritma, x değişkenini korumakta olan kilitlerin varlığını, herhangi bir t iş parçacığının x’e erişiminde LH(t) ∩ LS(x) işleminin sonucunu LS(x)’e eşitleyerek tutar. LS(x) x’e ilk erişimden önce tanımsızdır ve denetlenmekte olan koşutzamanlı programın bir iş parçacığı x’e ilk erişim yaptığında evrensel kilit kümesine eşit olacak şekilde ilklenir. LS(x)’i boş kümeye eşitleyen bir erişim sonrasında yarış durumu tespit edilmiş olur.

2.2. Çalışma zamanı gözlemlemenin işletim yükleri

Eraser algoritmasının uygulanmasında (i) çalışma izini oluşturan olayları, kaynak kodu veya makina kodu gözlem araçlarıyla gözlemlemek ve (ii) bu gözlemden toplanan olayların kilit kümesi veri yapılarını güncellemesini yapmak ve bu yapıları bazı özelliklere uyduğunu devamlı kontrol etmek gerekir (örneğin, LS(x) kümesi boş küme mi?). (i) işi iki şekilde uygulanabilmektedir, (a) olay oluştuğunda derhal Eraser fonksiyonlarının çağırılması ve ya (b) olayların oluştukça, daha sonra denetlenmek üzere geçici olarak bağlı listeye kaydedilmesi. Denetleyici uygulamaların başarımını etkileyen iki ana işletim yükünden bahsedebiliriz: (i) Gözlemleme yükü, yani çalışma olay takibi ve (b)’ye özel

bu olayların bağlı listeye kaydının toplam yükü. Eraser algoritmasında, her paylaşımlı bellek olayları (shared memory operation) ve eşzamanlı olaylarını gözlemlemek gerekir. Olayların sayısı ve turu arttıkça gözlemleme yükü artar, dolayısıyla olayların frekansı arttıkça olağan çalışmanın aksamasına ve olayların kendi başlarına az zaman almasına rağmen başarım kaybına sebep olur. 5. bölümdeki deneylerimizin sonuçları gösteriyor ki başlı başına

Page 3: KUDA: GPU Hızlandırılmış Ayrık Yarış Durumu Denetleyici

koşutzamanlı programı gözlemleme (denetleme yükü yokken) işletim yükü 1.6’dan 7.1’e kadar ek yük bindirebilmektedir. (ii) Denetleme yükü, yani algoritma bazlı veri yapılarının

güncellenip kontrol edilmesinin toplam yükü. Çalışma zamanı denetleme algoritmaları genellikle çalışma izinin tutulması/işlenmesi için denetlenen programın iş parçacıkları arasında paylaşılan bazı veri yapıları kullanır. Eraser algoritmasında kullanılan yapı kilit kümeleriydi. Diğer algoritmalar ise: bir değişkene erişen son iş parçasına imleç tutabilir ve buna ek olarak her iş parçası tarafından kullanılmak üzere her kilit için sanal saat vektörü (vector clock) de tutabilir. Bu veri yapılarına yapılacak koşutzamanlı erişimler ve işlemler oldukça yüksek frekansta olabilir, dolayısıyla eniyilenmemiş bir veri yapısı farklı denektaşı programlarında oldukça fazla başarım farkına yol açabilir.

Eraser için düşünürsek, denetleme yapacak iş parçalarının kilit kümelerine erişmesi için öteki iş parçacıklarıyla paylaşılmakta olan kilit veya kilitleri açması gerekir. Bu da uzun kritik bölümlere (bölünmeden çalışması gereken olaylar dizisi) sebebiyet verir ve programın başarımını ciddi şekilde düşürür. Sonuç olarak, Eraser gibi basit ve hafif çalışma yüküne sahip bir yarış durumu denetleme algoritması bile oldukça düşük çalışma hızı ve bellek boyutu başarımlarina sahiptir. Düşük başarıma sebep olacak yazılım çerçeveleri de hiçbir zaman son tüketicinin kullanacağı programlara uygulanamaz. Yarış durumlarının en belirgin özelliği eğer denetlenmezler ise tekrar açığa çıkması için aynı program, aynı ortamda milyonlarca defa tekrar calistirilsa dahi tekrar gozlemlenmeyebilir. Bu da bilgisayarlarının başındaki kullanıcılara “sebepsizce” kapanan programlar olarak yansımaktadır.

Biz, denetlemeden kaynaklanan işletim yükünü düşürebilmek için, öncelikle denetleyici algoritmaların iş yükünü denetlenen programın iş parçacıklarından ayırıp başka iş parçacıklarında, hatta başka işlemcilerdeki iş parçacıklarına yüklüyoruz. Çerçevemizde işlemci olarak grafik işlemcisine ait yüzlerce çekirdeği kullanmaktayız. Bu orijinal düşünceye sahip çerçevemizi gerçekleştirirken grafik işlemcisinde çalışacak olan denetleme algoritmalarının kaynak kodunun şaşırtıcı olarak geleneksel uyarlamalarına göre oldukça basitleştiğini gördük.

Son yıllarda yarış durumu denetleyicilerinin işletim yükünü düşürmek için çok sayıda oldukça başarılı girişimler oldu. Bu girişimler sanal makinelerde basarım adına kullanılan ara dillerini tam zamanında (just-in-time) derlenmeden önce denetlemekten [8,9], merkezi işlem ünitesinin basarım sayaçlarını gözlemleme için kullanmaya [10] ve çekirdek program çağrılarının örneklenmesine kadar [11] değişiklik ve orijinallik göstermektedir. Kazanılan basarım, denetlenen programlarda %1 yavaşlama gibi değerlere varabilmektedir. Ancak bu çalışmaların sonucunda yaşanan duyarlılık kayıpları,

yanlış ret hataları göz ardı edilmektedir. Koşutzamanlı programların gözetleme işletim yükünü düşürmek için de çok sayıda başarılı girişimler oldu, özelleştirilmiş donanım desteği kullanılarak, dinamik denetleme aracı kullanmaya gerek olmadan, yüksek başarımlı çalışma izi toplama yaklaşımını örnek verebiliriz [12]. Bizim çerçevemizde, henüz yaygın olmayan donanım destekleri kullanmamayı hedefledik. İleride işletim yükünü eniyilemek için böyle bir araştırma yönü düşünülebilir.

3. Yaklaşımımız 1: Genel Sistem Önceki bolümde anlatılan zorluklara binaen ana amacımız çalışma zamanı denetleme çerçevesi oluştururken denetlenecek programın başarımını asgari etkilenmesidir. Çerçevemizdeki anahtar tasarım ve orijinallik, denetleme algoritmasını fiziksel olarak ayrık bir işlemcide koşutzamanlı olarak çalıştırmamızdır. Kuda projesi kapsamında, denetleme algoritması yarış durumlarını denetler, ayrık işlemci ise grafik işlemcisidir. Merkezi işlemci biriminde koşmakta olan uygulama iş parçacıklarına yalnızca (kendi olaylarını) gözlemleme ve bu gözlemleri paylaşımlı bir veri yapısına iletme yüklerini ayrıca yüklüyoruz. Bu görevlerin nasıl paylaşıldığının detayını Şekil 1’de görebilirsiniz.

Bu bölümde çalışma izinin kaydını, paylaşımlı veri yapısını ve grafik işlemcisiyle iletişiminde kullandığımız tekniklerimizi anlatacağız. Bir sonraki bolum ise yalnızca grafik işlemcisindeki çekirdek (kernel) programa odaklanacak.

3.1. Çalışma izinin gözlemlenmesi

Çalışma izini gözlemlerken kullanacağımız tekniği seçerken, gerçekleşen olayların olabildiğince hızlı ve etkin bir şekilde veri yapısında dizilmesine önem verdik. Çalışma izinin çerçevelere bölünmesi ve veri yapısının dönüşsel bağlı liste kullanarak tutmamızın sebebi bir uçtan boş çerçevelerin doldurularak öteki uçtan grafik işlemcisine çerçeve yollanabilmesi, dolayısıyla çalışma izinin son derece etkin şekilde kullanılmasıydı. Deneylerimiz sonucunda çerçevenin tuttuğu olay sayısı, diğer bir deyişle çerçeve boyutu (FRAMESIZE), 1024 olay olarak eniyilenmiştir. Grafik işlemcisindeki denetleyici programın iş parçacıkları her çerçeveyi ayrı bir girdi olarak algılar ve çerçevelerin birbirlerinden bağımsız olarak işler. Denetleyici iş parçacıklarının farklı çerçeveleri denetlerken belleklerinde tuttuğu tek bilgi –sonraki çerçevelerde aynı değişkenleri denetlememek için- denetlediği yarış durumlarına sebep olan değişkenlerdir. Çerçevenin denetlenmesi bitince, eski çerçevenin üstüne yeni çerçeve kopyalanır ve aynı iş parçacıkları tekrar denetlemeye başlar.

Şekil 1: Çerçevemizin bileşenleri

Page 4: KUDA: GPU Hızlandırılmış Ayrık Yarış Durumu Denetleyici

Çalışma izinin çerçevelere bölünmesi ve birbirinden bağımsız denetlenmesi tabiatıyla, teorik olarak bazı yarış durumlarının kaçırılmasına sebep olur. Bu çerçevede eğer yarış durumuna sebep olan olaylar birbirinden 1024 olaydan fazla ayrılmış ise yarış durumlarını denetleyemiyoruz. Ancak çerçeve boyutunun büyütülmesi ve bundan doğacak başarım kaybı ile daha güvenilir (sound) yarış durumu denetleyebiliriz.

Çerçevemiz bu mühendislik tercihini kullanıcının ayarlayabilmesine olanak sağlamaktadır. Bu bildiri kapsamında henüz çerçeveleme tekniğinden dolayı kaçırılan yarış durumlarının analizini yapmadık, yapılan çalışmalarımız yalnızca çerçevemizin başarım artırımı kapsamında elverişliliğini göstermek adınaydı. Keza, konu üzerinde çalışan araştırmacıların çalışmalarında sunulan deneyler gösteriyor ki, koşut zamandan kaynaklanan hataların çoğu az sayıdaki iş parçasının çalışmalarının çok kısa bir parçasında oluşmaktadır [13].

Şekil 2’de çalışma izinin dönüşsel bağlı listede nasıl tutulduğunu görebilirsiniz. Bu bağlı listede her FRAMESIZE adetinde olayın farklı çerçevede tutulabildiği sabit sayıda çerçeve vardır. Aşağıda anlatıldığı gibi, dönüşsel bağlı liste veri yapısı çalışma izinin hızlı ve etkin biçimde kullanılmasını sağlar. Kod parçası 1’de olayların çerçevelere doldurulması (OlayKaydı) ve dolu çerçevelerin işlenmesini

(ÇerçeveDenetle) anlatan yalancı kodları gösteriyor. OlayKaydı denetlenen programın iş parçacıkları tarafından, ÇerçeveDenetle işe bu iş için yaratılmış ayrı bir iş parçacığı tarafından, merkezi işlemcide yürütülür.

Çerçeve listesi bloklamayan algoritmalar ve birkaç bölünmez yönerge (instruction) ile kullanılır; yani iş parçacıklarının erişmesi veya çalışma izinin grafik işlemcisine yollanması için özellikle kilit açmalarına gerek yoktur. Listenin kullanımı boyunca iki adet veri imleci (pointer) tutuyoruz: Kafa ve Kuyruk imleçleri. Dönüşsel bağlı listede çalıştıklarından dolayı Kafa ve Kuyruk değerleri her türlü (liste için ayrılan) bellek değerlerine denk gelebilir; Kafa ve Kuyruk aynı yönde ilerletilir. Şekil 2’de Kafa’nın sağından Kuyruk’a kadar, boş çerçeveler vardır (beyaz renkli). Kafa’nın bulunduğu çerçeve işe o anda doldurulmakta, Kuyruk ise boşaltılacak olan çerçeveyi temsil eder. Gri çerçeveler dolmuştur ve GİB’e (Grafik İşlem Birimi) gönderilmek için Kuyruk’un Kafa’ya yetişmesini beklerler. Çerçeve listesi ilk oluşturulduğunda Kafa ve Kuyruk aynı çerçeveyi gösterir. Çerçeve tamamen dolduğunda Kafa bir sonraki boş çerçeveye ilerletilir, çerçeve GİB’e gönderildiğinde Kuyruk bir sonraki dolu (veya dolmakta olan) çerçeveye ilerletilir. Kafa ve Kuyruk çerçeve okumaları sırasında oluşacak yarış durumlarını önlemek için Kafa ve Kuyruk imleçlerini bölünmez yönergelerle kullanıyoruz.

3.1.1. Olayların Kaydedilmesi (Kod parçası 1: OlayKaydı)

Her çerçeve sabit bir boyuta sahiptir ve bu sayıda olay tutmaktadır. Bir uygulama iş parçası olay kaydetmek istediğinde, listeyi Kafa’dan başlayarak tarar (1-7 numaralı satırlar). Bölünmesiz (atomic) yönergelerle olmak üzere, çerçevedeki olay sayısını okunur ve bu sayı bir arttırılır (2-6 numaralı satırlar). Eğer okunan olay sayısı çerçeve boyutundan (FRAMESIZE) küçükse, kayıt edilecek olay çerçevenin o indeksine kaydedilir (8. satır). Eğer o sayı çerçeve boyutuna eşit veya büyükse (eğer büyükse Kafa ilerletilemeden birden fazla iş parçacığı aynı ve dolu çerçeveye yazmak istemiş demektir), kayıt için çalışan iş parçacığı bir sonraki çerçeveye bakar (3-7 numaralı satırlar). İş parçası Kafa çerçevesinin son indeksine olay kaydetmiş ise Kafa’yı ilerletir (9. satır). Eğer bir iş parçacığı bir sonraki çerçeveye kayıt için çalışırken bu çerçevenin Kuyruk çerçevesi olduğunu görürse, tekrar Kafa'dan taramaya başlar (1. satır). Bu duruma aç kalma (starvation) durumu diyoruz. Deneylerimizde 64 adet çerçeveyle oluşturulan listede hiçbir aç kalma durumu gözlemlemedik, bu da çerçevelerin denetiminin, olay kaydı hızından ortalama olarak daha hızlı olduğunu gösteriyor.

3.1.2. Çerçeve İşlenmesi (Kod parçası 1: ÇerçeveDenetle)

Çerçeveleri Kuyruk’tan kopyalayıp grafik işlemcisine yollamak için oluşturulan bir iş parçası olduğundan

Şekil 2: Çerçeve listesinde kullanılan veri yapısı detayları

e

1 cerceve Kafa

2 i AtomicGetAndIncrement(cerceve.boyutu)3 i � FrameSize

4 cerceve = Kuyruk

5 cerceve cerceve.next

6 i AtomicGetAndIncrement(cerceve.boyutu)7

8 cerceve[i] e

Kafa

9 i = FrameSize� 1 Kafa Kafa.next

1

2 Kafa 6= Kuyruk

3 cerceve Kuyruk

cerceve

4 cerceve

5

Kuyruk

6 cerceve.boyutu 07 Kuyruk cerceve.next

8

9

10

Kod parçası 1

Page 5: KUDA: GPU Hızlandırılmış Ayrık Yarış Durumu Denetleyici

bahsetmiştik. Kuyruk imleci önceki bölümde bahsedildiği gibi, çerçeve listesinde ilk dolmuş olan çerçeveyi gösterir. Yani grafik işlemcisine gönderilecek ilk çerçeve Kuyruk çerçevesidir (Şekil 2’de en sağdaki çerçeve). Bunu etkin şekilde yapması için, iş parçası, denetlenen program sonlanmadığı (sonlandıysa bile Kuyruk’un Kafa’yı yakalamadığı) sürece dönen bir döngü içindedir. Her döngüde ilk olarak Kafa ve Kuyruk’un farklı çerçeveye bakmasını (listede dolu çerçeve oluşmasını) bekler (2. satır). Bu durum oluştuğunda, Kuyruk çerçevesi GİB’e yollanır. (3. satır). Bölüm 4.1’de 4-5 ve 8-9 numaralı satırların detayını ve GİB’deki çalışan denetleme algoritmasını Kod parçası 2’de bulabilirsiniz. GİB’deki çekirdek program asenkron olduğu için, iş parçası bu süre içinde gönderilen çerçeveyi boşaltır (6. satır) ve Kuyruk’u bir ilerletir (7. satır). Çekirdek programlar sonlanıncaya kadar bekleyip (8. satır), denetleme sonuçlarını (Kuda kapsamında yarış durumlarını) GİB (Grafik İşlem Birimi) belleğinden MİB (Merkezi İşlem Birimi) belleğine kopyalar (9. satır). Çerçevemiz, yapılanışı değiştirilerek, yarış durumlarının görüldüğü anda veya denetlenen programın sonlanması durumunda hata bildirimi yapabilir.

4. Yaklaşımımız 2: Çerçevelerin GİB’de denetlenmesi

3. bölümde çerçevemizin MİB’de koşan parçalarına odaklandık, bu bölümde ise GİB’de çalışan çekirdek programları ve koşutzamanlı yarış zamanı denetim algoritmalarına odaklanacağız. Öncelikle kısaca GİB programlama konseptini ve bu alanda karşılaşılan zorlukları anlatacağız. Ardından Eraser ve Goldilocks algoritmalarının bu konsepte nasıl uydurduğumuzu anlatacağız.

4.1. CUDA kullanarak GİB programlama

CUDA modeli programlamacıya, C programlama dilinin bir uzantısı olan CUDA programlarını derleyen bir derleyici ve C programlarından çağırılabilecek uygulama programlama arabirimi sağlamaktadır. Ayrıca fiziksel katmanının yazılım katmanından ayrı, etkin bir şekilde yürütülmesini sağlar, böylece aynı CUDA programı farklı CUDA grafik işlemcilerinde sorunsuzca çalışabilir.

GİB’de koşacak her kod parçası, C/C++ dilinde yazılmış ve MİB’de koşan bir programdan çağrılan bir çekirdek program çağrısı aracılığıyla koşturulur. Yani çerçevemizde kullandığımız denetleme algoritmaları birer CUDA çekirdek programı olarak yazılmıştır ve bu programlar da Kod parçası 1’deki ÇerçeveDenetle fonksiyonu içinden çağırılır. MİB ve GİB iş parçacıkları fiziksel olarak izoledir, eşzamanlama yalnızca bir iş parçacığının çekirdek programları çağırıp, denetlenecek çerçeveyi iletmesi ve ardından fark edilen yarış durumlarını MİB’e kopyalaması sırasında olur, bunun dışında iki işlemci asenkron çalışmaktadır. Denetlenen program ise hiç bir şekilde GİB’deki çekirdek programlar ile eşzamanlama ihtiyacı duymaz. Asenkron çalışabilmek için denetlenecek çerçevenin GİB’e kopyalanabilmesi gerekir, bunun için de program başlatılmadan önce GİB’de özel bellek konumu ayrılmaktadır. Çekirdek programlarda oluşan ara sonuçları ve sonuçları da tutabilmek için ayrıca fazladan bellek ayrılır. Bu bellek konumlarını gösteren imleçler çekirdek program çağrılarında GİB’e parametre olarak iletilir. MİB’de koşan, çerçeve iletişimi ve çekirdek program çağrılarından sorumlu olan iş parçacığı aşağıdaki adımları izlerken CUDA uygulama programlama arabirimi çağrılarını kullanır:

• Denetlenecek çerçevenin GİB’e kopyalanması • Çekirdek programların gerekli parametreler ile çağrılması

(SIMD (tek program-çoklu veri) stili ile çalışmaktadır) • Çekirdek programların sonucunu MİB’e kopyalamak için

eşzamanlama GİB programlamadaki zorluk, işlenecek verilerin yukarıda

da anlatıldığı gibi MİB’den aktarılması ve verilerin geri alımı sırasındaki eşzamanlamadan ötürü kaybedilen başarımın koşutzamandan dolayı telafi edilebilir olup olmamasıdır. Denetleme algoritmalarımızda her iş parçası kendine düşen olayda geçen değişken üzerinde yarış durumu denetimi yapmaktadır. Yani kilit kümeleri gibi denetleme veri yapıları her iş parçasına yerel olarak, paylaşımsız yaratılıp kullanılır. Bu da çekirdek programların birbiriyle asenkron çalışmasını sağlar. Çekirdek programları http://kuda.codeplex.com bağlantısından inceleyebilirsiniz.

Ancak GİB programlamadaki tek zorluk zaman değildir; oldukça kısıtlı olabilen bellek boyutları, çekirdek programların paylaştığı çerçeve sadece okunduğundan geniş paylaşımlı belleğe konulabilmektedir. Ancak denetleme sırasında kullanılacak denetleme veri yapıları için de önceden yer ayırmak gerektiğinden, bu veri yapılarını sınırlandırdık. Eraser ve Goldilocks programlarında bu veri yapılarını bloom filtreleri ile gösteriyoruz. Bloom filtre veri yapıları, bellek konumu kümelerini sabit boyuttaki bit kümelerinde tutabilir. Tek bir denetleme için gereken veriler sınırlı sayıda, yerel olarak ve geçici şekilde kullanıldığından dinamik şekilde yaratılan diğer objelerin bellek boyutunu zorlaması söz konusu olmamaktadır.

5. Deneyin Değerlendirilmesi

Çerçevemizin elverişliliğini göstermek için iki hedefi tutturduğumuzu doğrulamamız gerekiyordu:

• Gözlemleme ve denetleme yüklerini iki ayrı işlemci birimine ayırmak, eklenen çalışma izi tutma ve çalışma izinin iletişimi yüklerine rağmen, denetleyici programları hızlandırabilir.

• GİB’de kosan denetleyici programın MİB’de kosan denetlenen program ile çok yakın zamanlı (birkaç milisaniye mertebesinde gecikmeyle) çalışabilir. Başka bir deyişle, program sonlandıktan kısa bir süre içinde denetleyici program da sonlanabilir.

Çerçevemizin bu hedeflere ulaştığını gösterebilmek için ön ürün olarak KUDA’yi yarattık ve iki koşutzamanlı çalışan denektaşı takımıyla sınadık. Toparlamak gerekirse, KUDA’da iki ana parça bulunmaktadır:

1. Koşutzamanlı program iş parçacıklarının olaylarının işletimini çerçevelerle sağlayan ve bu çerçevelerin GİB’de yarış durumlarını denetleyen çekirdek programdan oluşan işletim içi bağlamalı program. Biz çekirdek programlarını yazmak ve çağırmak için CUDA 4.0 kütüphanesini [5] kullanıyoruz. Deneylerimizde GİB belleği olarak genel paylaşımlı bellek modelini kullansak bile, çerçevemizi sabit veya doku bellek modellerini kullanacak şekilde eniyilememiz mümkün. Çünkü denetlenen çerçevelerin yüzlerce iş parçacığı tarafından yalnızca okunması buna imkan kılıyor.

2. Denetlenecek olan koşutzamanlı programdaki paylaşımlı bellek okuma/yazma, iş parçacığı yaratma/birleştirme ve iş parçacığı eş zamanlama

Page 6: KUDA: GPU Hızlandırılmış Ayrık Yarış Durumu Denetleyici

gibi POSİX iş parçacık standardına (pthreads kütüphanesi) dahil çağrıların ve genel olayların dinamik olarak gözlemlenmesini sağlayan bir Pin aracı [4].

5.1. Deney Düzeneği

5.1.1. Denektaşları

Deneylerimizde KUDA’yı 2 denektaşı takımıyla sınadık, PARSEÇ [6] ve SPLASH-2 [7]. Bu denektaşları C/C++ dilinde, pthread modelini kullanarak koşutzamanlı çalışan programlardır. Ortalama bir çalışmada bu denektaşları birkaç yüz milyon olay, dolayısıyla yüz binlerce çerçeve yaratılmakta ve her dolu çerçeve de grafik işlemcisinde denetlenmektedir. Daha detaylı bilgi için Tablo 1’e bakınız.

5.1.2. Donanım

Deneylerimizi HP xw9300 model iş istasyonunda, Ubuntu Linux 10.10 32 bit çekirdekli işletim sisteminde gerçekleştirdik. MİB olarak çift çekirdekli, 2600 MHz saat frekanslı, 128 KB L1, 1 MB L2 on bellekli, 400 MHz’de çalışan 8 GB bellekli AMD Opteron’dur. GİB olarak ise Fermi uyumlu GeForce GTX 465 ekran kartını kullandık. Bu grafik işlemcisinde 1.21 GHz saat frekanslı, 1.23 GB bellekli 352 adet CUDA çekirdeği bulunmaktadır. Bu da iki işlemci arasında 1.4 GB/sn., grafik işlemcisi içinde ise 71.3 GB/sn. bellek bant genişliğine denk gelmektedir.

5.1.3. Yapılanış

Farklı yapılanışlarda gözlemlediğimiz yüzlerce denektaşı koşusunda şu değerlerin KUDA’nın başarımını en üst noktaya çıkardığı kanaatine vardık: • Çerçeve boyutu (FRAMESIZE): 1024 olay • Çerçeve sayısı: 8192 çerçeve • MİB’deki bellek izdüşümü: 8192 çerçeve * 1024 olay * 8

bayt (her olay) = 64 MB

• Her çerçevede 128 GIB iş parçacığı çağırılır. • Her çerçevede 128 sıralı olay dizisi yollanır (her iş

parçacığına bir çerçeve düşüyor)

6. Sonuçlar Tablo 2’deki deney sonuçları gösteriyor ki koşutzamanlı bir programın Pin aracıyla boş gözlemleme fonksiyonlarının çağrılması dahi 1.6 ile 7.1 kat arasında başarım kaybına sebep olmaktadır.

Kendi yaklaşımımız ile geleneksel yaklaşımlar arasındaki başarım farkını karşılaştırabilmek için Eraser algoritmasının yanında saat vektörü tabanlı iki modern yarış durumu denetleyicisini, DJIT+ [14] ve Fasttrack [15], Pin aracıyla çalışacak şekilde C/C++ dilinde geliştirdik. Bu geliştirilen destek programlar orijinal bildirilerdeki kadar eniyilenmemiş olmakla beraber, göreceli başarımları hakkında fikir verebilmektedir.

Yaptığımız destekleyici deneylerde DJIT+ ve Fasttrack denetleyicilerinin başarımı Eraser denetleyicisinin başarımından oldukça düşüktü. Dolayısıyla Eraser denetleyicisi, geleneksel yarış durumu denetleyicileri içinde en basiti olmakla beraber göreceli olarak daha hızlı çalışan bir denetleyicidir. Ancak Eraser denetleyicisinin en az 31.4 kat başarım kaybına yol açtığını unutmamak gerekir. Sonuç olarak, geleneksel yarış durumu denetleyicilerinin birkaç yüz kat başarım yavaşlattıklarını gözlemledik. Diğer denetleyicilerin avantajı ise Eraser algoritmasına göre daha güvenilir çalışmalarıdır. Örneğin Fasttrack denetleyicisinde, Eraser denetleyicisinin aksine yanlış kabul hatası (false positive error) oluşmaz. Goldilocks ve Fasttrack yarış durumu denetleyicileri eksiksizdir, ne yanlış kabul ne de yanlış ret hatası verir.

KUDA’da geliştirdiğimiz denetleyici çekirdek programları iki tanedir: Eraser ve Goldilocks algoritmaları. Deneylerimizde Eraser çekirdek programıyla koşan KUDA, Goldilocks gibi karmaşık bir denetleyici programıyla koşan KUDA’dan yalnızca biraz daha yüksek başarıma sahiptir. KUDA’nın iki farklı versiyonunda da denetleme programları,

Benchmark Description Lines #Threads #Events #FramesPARSECblackscholes (L) Black-Scholes partial di�erential equations 1661 9 238M 224Kbodytrack (L) tracking human body with multiple cameras 7385 10 2707M 2.6Mcanneal (L) cache-aware simulated annealing 1793 9 468M 449Kdedup (M) data stream compression 3681 25 1993M 1.9Mfluidanimate (L) simulating incompressible fluid 945 9 2461M 2.3Mraytrace (S) optimized ray tracing >6K 9 332M 316Kstreamcluster (S) online clustering problem 2531 9 178M 166Kswaptions (L) monte carlo simulation 1615 9 2731M 2.6Mx264 (M) H.264/AVC video encoder 3014 64 1460M 1.4MSPLASH-2barnes Barnes-Hut for N-body problem 3507 4 3035M 2.9Mcholesky blocked sparse cholesky factorization 5684 8 269M 254Kfmm adaptive fast multipole for N-body problem 5434 4 1629M 1.5Mfft complex 1D FFT 1462 8 577M 556Klu blocked LU decomposition 1380 8 1087M 1Mocean large-scale ocean simulation 8176 8 531M 510Mradix integer radix sort 1530 8 302M 287Kraytrace optimized ray tracing 11043 9 332M 316Kwater-nsquared water simulation w/out spatial data structure 3098 4 3120M 7.2Mwater-spatial water simulation with spatial data structure 3655 4 727M 701K

Table 1. Description of our benchmarks, and number of events and frames generatedat a typical run. For the PARSEC benchmarks the input size is given in parantheses((S):simsmall, (M):simmedium, (L):simlarge), and for the SPLASH-2 benchmarkswe used the default inputs except that some values are taken from Table 1 of [1].

a prototype tool called Kuda and applied Kuda on a collection of multithreadedbenchmarks. Kuda consists of two parts:

1. A dynamic library containing the core functionality including the routinesfor recording events, managing event frames, and running the race detectionkernels on the GPU. We use the CUDA 4.0 library [8] to write and call kernelsfor analyzing frames and to manage the GPU resources (e.g., transferring datato/from the GPU device memory). While our experiments are performed usingthe global memory, our system can use constant and texture memory. The factthat event frames are only read by the kernel enables us to make use of theconstant and texture memory, which are cached for fast read-only access.

2. A Pin [6] tool to dynamically instrument x86 binaries in order to callback theroutines in our dynamic library on certain events (shared memory read/write,thread creation/join, and inter-thread synchronization). Our Pin tool supportsmultithreaded programs written using the pthreads library (for thread cre-ation and join, and synchronization primitives including mutex and reader-s/writer locks).

5.1 Experiments

Benchmarks. We applied our tool Kuda on a collection of multithreaded pro-grams from PARSEC [2] and SPLASH-2 [11] benchmark suites. The names, briefdescriptions, sizes (lines of code) of these programs are listed in Table 1. Thetable also gives, for each benchmark, the number of threads, events, and framesgenerated in a representative execution of the benchmark. Notice that, in a typi-cal execution, our benchmarks generate a few hundreds of millions of events andhundreds of thousands of frames, each of which is checked on the GPU.

12

Tablo 1: Denektaşları, açıklamaları, iş parçacık sayıları ve ortalama olay/çerçeve sayıları

Page 7: KUDA: GPU Hızlandırılmış Ayrık Yarış Durumu Denetleyici

denetlenen programın sonlanmasından ortalama 2.5 milisaniye sonra sonlanmaktadır. Tekrar hatırlatmak gerekir ki, KUDA’da sabit sayıda çerçeve vardır (8192), çerçeveler kullanıldıkça yeni çerçeve yaratılması yerine eski çerçeveler geri kullanılır. Bu durum ve iki işlemcinin asenkron şekilde yalnızca 2.5 milisaniye farkla programın sonuna gelmelerinden, iki ayrı çalışma zamanının birbirine çok yakın olduğunu, kısacası GİB’in MİB’den arkada kalmadığını gösteriyor.

Tablo 2’deki sonuçlar açıkça gösteriyor ki, koşutzamanlı bir programın güvenilirlik özelliklerinin grafik işlemcideki iş parçacıklarında denetlenmesi, geleneksel çalışma zamanı doğrulama tekniklerinin başarımını çarpıcı olarak arttırmaktadır. MİB’de yarış durumu denetleme ile GİB’de bizim çerçevemizle yarış durumu denetleme arasında en kötü 3.3, en iyi 14.7 kat başarım artımı gözlemledik. Denektaşlarından yalnızca streamcluster programının MİB’de yarış durumu denetlemek GİB’de denetlemekten daha hızlı oldu, bunun nedeni ise denektaşının yüzbinlerce bariyer eşzamanlama mekanizması kullanmasıdır. Raytrace denektaşlarının ise MİB’deki yarış durumu denetlemeleri yarım saatten daha fazla sürdüğünden dolayı yarıda kaldı; ancak bu denektaşlarının sonlanmasına izin verseydik 17-20 kat hızlanma gözlemlemiş oluyorduk.

Son olarak, “Only with Events” ile “Goldilocks on GPU” sütunlarındaki oldukça düşük farka dikkat etmeliyiz. Bu farktaki düşüklük bize, programın gözlemleme, olay kaydı, çerçeve listesinin GİB’e gönderilmesinin çerçevemizdeki zamanın çoğunu aldığını göstermiş olmaktadır. Aradaki başarım oranı en fazla blackscholes denektaşındadır, o da yalnızca 1.4’tur. Olayların (yazılımsal) kaydının bu kadar yavaş olmasına rağmen GİB’de koşan denetleyicinin ön ürün olmasına rağmen yalnızca %40 yavaşlamaya sebep olması, ilerideki araştırmalarımız için son derece cesaretlendiricidir. Araştırmamıza dair daha detaylı bilgiyi İngilizce teknik raporumuzda [16] bulabilirsiniz.

7. Kaynakça [1] Poletti Francesco, Poggiali Antonio ve Paul Marchal,

“Flexible hardware/software support for message passing on a distributed shared memory architecture”, DATE, Washington, DC, USA, 2005, s. 736-741.

[2] Stefan Savage, Michael Burrows, Greg Nelson, Patrick Sobalvarro ve Thomas Anderson, “Eraser: a dynamic data race detector for multithreaded programs”, ACM Trans. Comput. Syst., vol. 15, no. 4, s. 391-411, 1997.

[3] Tayfun Elmas, Shaz Qadeer ve Serdar Tasiran, “Goldilocks: a race ve transaction-aware java runtime”, PLDI, 2007, s. 245-255.

[4] Chi-Keung Luk, Robert Cohn, Robert Muth, Harish Patil, Artur Klauser, Geoff Lowney, Steven Wallace, Vijay Janapa Reddi ve Kim Hazelwood, “Pin: building customized program analysis tools with dynamic instrumentation”, PLDI, 2005, s. 190-200.

[5] NVIDIA Corporation, NVIDIA CUDA Programming Guide v4.0, NVIDIA Corporation, 2011.

[6] Christian Bienia, Sanjeev Kumar, Jaswinder Pal Singh ve Kai Li, “The parsec benchmark suite: Characterization ve architectural implications”, Tech. Rep. TR-811-08, Princeton University, Ocak 2008.

[7] Steven Cameron Woo, Moriyoshi Ohara, Evan Torrie, Jaswinder Pal Singh ve Anoop Gupta, “The splash-2 programs: characterization and methodological considerations”, ISCA, 1995, s. 24-36.

[8] Christoph von Praun ve Thomas R. Gross, “Object race detection”, OOPSLA, New York, NY, USA, 2001, s. 70-82.

[9] Yuan Yu, Tom Rodeheffer ve Wei Chen, “Racetrack: efficient detection of data race conditions via adaptive tracking”, SOSP, 2005, s. 221234.

[10] Tianwei Sheng, Neil Vachharajani, Stephane Eranian, Robert Hundt, Wenguang Chen ve Weimin Zheng, “Racez: a lightweight and noninvasive race detection tool

Benchmark Uninstr. Only Instrumented Eraser on CPU Only with Events Goldilocks on GPURuntime Runtime Slowdown Runtime Slowdown Runtime Slowdown Runtime Slowdown

PARSECblackscholes 1.31 2.83 2.1X 136.04 101X 20.89 14.7X 29.27 21.1Xbodytrack 4.11 10.93 2.6X 1044.48 251X 305.11 72.5X 317.58 75.6Xcanneal 8.85 14.81 1.6X 431.04 47X 67.5 6.9X 71.66 7.4Xdedup 2.25 7.06 3.1X 972.12 429.9X 202.94 88X 233.56 101.6Xfluidanimate 3.29 8.46 2.5X 1024.52 308X 281.27 83.9X 295.24 88.1Xraytrace 14.43 29.35 2X >30min >123.7X 98.24 5.7X 105.37 6.2Xstreamcluster 7.27 22.72 3.1X 244 31.4X 419.21 55.5X 434.94 57.7Xswaptions 2.61 8.01 3X 1150.97 437X 312.26 117.5X 318.57 119.9Xx264 1.09 7.84 7.1X 710.12 645.2X 172.2 151.7X 176.66 155.8XSPLASH-2barnes 3.08 7.61 4X 1542 499.1X 348.12 111.5X 362.12 116.1Xcholesky 0.94 3.04 3.2X 205.34 216.2X 32.61 32.4X 33.39 33.2Xfmm 1.85 5.53 2.9X 2697 1455.8X 169.45 89.6X 186.21 98.6Xfft 1.47 3.2 2.1X 329.21 222.7X 68.42 45.3X 72.52 48.1Xlu 0.44 2.63 5.9X 477 742.2X 123.6 190X 131.21 201.9Xocean 0.86 3.47 4X 262 301.6X 57.21 63.4X 61.21 68.1Xradix 1.07 2.18 2X 136.62 126.6X 34.45 31.1X 36.53 33.1Xraytrace 14.6 30 2X >30min >122.2X 117.4 6.9X 120.46 7.2Xwater-nsquared 4.61 16.18 3.5X 3274 707.6X 851.35 182.1X 894.12 191.4Xwater-spatial 0.63 2.91 4.6X 308 485.2X 74.67 114.9X 85.14 131.5X

Table 2. Results from our experiments. Running times are given in seconds.

Hardware. We performed our experiments on a HP xw9300 Workstation run-ning Ubuntu Linux 10.10 32-bit kernel. Our machine has two (single-core) AMDOpteron processors with 2600 MHz clock frequency, 128 KB L1 cache, 1 MB L2cache, and 8 GB memory (400 MHz). We used a GeForce GTX 465 GPU cardwith Fermi chipset. Our card provides 352 cores (11 processors with 32 cores each)with 1.21GHz clock rate, 1.23 GB of memory space with 1.4 GB/sec host-to-devicememory bandwidth and 71.3 GB/sec in-device memory bandwidth.Configuration parameters. For the experiments, we chose the following pa-rameters that gave the best results in terms of runtime and memory overhead. Weselected the event frame size (FrameSize) to be 1024 events. We initialize thecyclic list in Fig. 2 with 2048 frames. Thus, our system requires only2048 frames * 1024 events (each frame) * 8 bytes (each event) = 16 MBytes ofmemory space to store the events for the CPU. We run 128 GPU threads overeach event frame. In order to get the maximum benefit from the GPU device’sconcurrent computing functionality, we collect and send to the GPU 128 consec-utive event frames at a time. In this way we aim to utilize the high parallelism onthe GPU to analyze multiple frames simultaneously.

5.2 Results

Table 2 gives the runtime measurements for several configurations we run for eachbenchmark. The column “Uninstr.” lists the running time of the benchmark with-out any instrumentation. For other columns, we report on both the running timeof the program and the slowdown in the execution over the uninstrumented run-time. The running times for all columns are given in seconds. When computing theslowdown for the columns “Eraser on CPU”, “Only with Events” and “Goldilockson GPU”, we subtract the instrumentation cost (i.e., “Only Instrumented” - “Unin-str.”) from the runtime before dividing it to the running time of “Uninstr”.

13

Tablo 2: Deneylerimizin sonuçları. Yürütüm süreleri saniye cinsindendir.

Page 8: KUDA: GPU Hızlandırılmış Ayrık Yarış Durumu Denetleyici

for production applications”, Proceedings of the 33rd International Conference on Software Engineering, New York, NY, USA, 2011, ICSE '11, s. 401-410, ACM.

[11] John Erickson, Madanlal Musuvathi, Sebastian Burckhardt ve Kirk Olynyk, “Effective data-race detection for the kernel”, Proceedings of the 9th USENIX conference on Operating systems design and implementation, Berkeley, CA, USA, 2010, OSDI'10, s. 1-16, USENIX Association.

[12] Shimin Chen, Phillip B. Gibbons, Michael Kozuch ve Todd C. Mowry, “Log-based architectures: using multicore to help software behave correctly”, SIGOPS Oper. Syst. Rev., vol. 45, s. 84-91, Şubat 2011.

[13] Madanlal Musuvathi, Shaz Qadeer, Thomas Ball, Gerard Basler, Piramanayagam Arumuga Nainar ve Iulian Neamtiu, “Finding and reproducing heisenbugs in concurrent programs”, OSDI, 2008, s. 267-280.

[14] Eli Pozniansky ve Assaf Schuster, “Multirace: Efficient on-the-fly data race detection in multithreaded c++ programs”, Concurr. Comput. : Pract. Exper., vol. 19, no. 3, s. 327-340, 2007.

[15] Cormac Flanagan ve Stephen N. Freund, “Fasttrack: efficient and precise dynamic race detection”, PLDI, 2009, s. 121-133.

[16] Tayfun Elmas, Semih Okur ve Serdar Tasiran, “Rethinking runtime verification on hundreds of cores: Challenges and opportunities”, Tech. Rep. UCB/EECS-2011-74, EECS Department, University of California, Berkeley, Jun 2011.