=Paper= {{Paper |id=Vol-2201/UYMS_2018_paper_25 |storemode=property |title=Saydam Artikli Calistirma Icin Vekil Tasarim Oruntusu Kullanimi(Using Proxy Design Pattern for Transparent Redundant Execution) |pdfUrl=https://ceur-ws.org/Vol-2201/UYMS_2018_paper_25.pdf |volume=Vol-2201 |authors=Dindar Oz,Sinan Oz,Isil Oz }} ==Saydam Artikli Calistirma Icin Vekil Tasarim Oruntusu Kullanimi(Using Proxy Design Pattern for Transparent Redundant Execution)== https://ceur-ws.org/Vol-2201/UYMS_2018_paper_25.pdf
   Saydam Artıklı Çalıştırma İçin Vekil Tasarım
              Örüntüsü Kullanımı

                          Dindar Öz1 , Sinan Öz2 , and Işıl Öz3
         1
           Yazılım Mühendisliği Bölümü, Yaşar Üniversitesi, İzmir, Türkiye
                                dindar.oz@yasar.edu.tr
      2
        MovieStarPlanet ApS, Kopenhag, Danimarka sinanoz1980@gmail.com
3
  Bilgisayar Mühendisliği Bölümü, İzmir Yüksek Teknoloji Enstitüsü, İzmir, Türkiye
                                   isiloz@iyte.edu.tr



       Abstract. Bu çalışmada, nesneye yönelik programların güvenilir bir
       şekilde çalıştırılması için saydam bir model önermekteyiz. Geçici do-
       nanım hatalarına karşı istenen seviyede güvenilirliği sağlayabilmek
       amacıyla artıklı (redundant) program çalıştırması için genel bir nesneye
       yönelik programlama aracı tasarladık. Bunun için yazılım sistemlerini
       esnek ve kolay sürdürülebilir yapabilmek için oluşturulmuş ve yaygınca
       kullanılan GoF tasarım örüntülerinden biri olan vekil tasarım örüntüsünü
       kullandık. Vekil tasarım örüntüsü, var olan bir nesneye erişirken ona yeni
       fonksiyonellikler eklemeye yarayan saydam bir düzenek ve kontrollü bir
       erişim sağlamaktadır. Java programlama dilindeki dinamik vekil ve an-
       notation araçlarını birleştirerek, artıklı çalıştırma ve çoğunluk oylaması
       için genel, saydam ve yapılandırılabilir bir araç olan RedundantCaller ’ı
       sunmaktayız. Aracımız, herhangi bir nesneyi alır ve özgün kullanıcı ko-
       duna en az miktarda değişiklik gerektirerek nesnenin metotlarını farklı
       iş parçacıklarında çoklu miktarda çalıştıran ve arka planda çoğunluk
       oylaması yapan bir dinamik vekil yaratır. annotationlar sayesinde, kul-
       lanıcılar artıklı çalıştırmayı metot seviyesinde yapılandırabilirler. Deney-
       lerimiz göstermektedir ki; aracımız herhangi bir nesneye yönelik program
       için çok iş parçacıklı çalıştırma sayesinde makul bir performans düşüşüyle
       kayda değer bir güvenilirlik seviyesi sağlamaktadır.

       Keywords: Nesneye yönelik programlama · Vekil tasarım örüntüsü ·
       Artıklı çalıştırma.
    Using Proxy Design Pattern for Transparent
              Redundant Execution

                        Dindar Öz1 , Sinan Öz2 , and Işıl Öz3
        1
        Software Engineering Department, Yaşar University, İzmir, Turkey
                           dindar.oz@yasar.edu.tr
     2
       MovieStarPlanet ApS, Copenhagen, Denmark sinanoz1980@gmail.com
 3
   Computer Engineering Department, İzmir Institute of Technology, İzmir, Turkey
                             isiloz@iyte.edu.tr



       Abstract. In this study, we propose a transparent model for reliable ex-
       ecution of object-oriented software. We design a generic object-oriented
       programming tool for redundant software execution to provide the de-
       sired level of reliability against transient hardware faults. To achieve this,
       we utilize the Proxy design pattern which is one of the well-known GoF
       design patterns that are formed to make software systems flexible and
       easy to maintain. Proxy design pattern provides a controlled access and
       a transparent mechanism for adding new functionalities to an existing
       object when accessing it. Combining the instruments of dynamic proxy
       and annotations in Java programming language, we present, Redundant-
       Caller, a generic, transparent, and configurable tool for redundant ex-
       ecution and majority voting. Our tool takes any object and creates a
       dynamic proxy for it which executes the methods of the object mul-
       tiple times in separate threads, and performs majority voting on the
       background, requiring minimum amount of change in the original user
       code. Thanks to annotations, users can configure the redundant execu-
       tion scheme methodwise. Our experiments demonstrate that our tool
       provides a significant level of reliability to any object-oriented software
       with a reasonable amount of performance degradation through multi-
       threaded execution.

       Keywords: Object-oriented programming · Proxy design pattern · Re-
       dundant execution.


1    Giriş
Bilgisayarlar ve üzerinde çalışan yazılımlar gün geçtikçe hayatın her alanında yer
alırken, bilgisayarların güvenilir çalışması önem kazanmaktadır. Askeri operasy-
onlar, sağlık, uzay araştırmaları, finansal işlemler gibi bazı uygulama alanlarında
bu sistemlerin işleyişlerinde meydana gelebilecek en küçük bir hatanın bile
kabul edilemez sonuçları olabilmektedir. Bu anlamda bilgisayar sistemlerini daha
güvenilir kılabilmek için uygulanabilecek yöntemler bilgisayar mühendisliğinin
önemli araştırma alanlarından biri olmuştur [1]. Artıklı sistemler bu yöntemlerin
başlıcaları arasındadır [2, 3]. Sistemin ya da sistemin işleyişinin gerekenden fazla
şekilde çoklanması temeline dayanan bu yöntem, donanımsal ya da yazılımsal
olarak uygulanabilmektedir. Donanımsal artıklı sistemler, çoklanan donanım
bileşeninin arıza yapması ve hatalı çalışması ihtimaline karşı uygulanmaktadır.
Bu sistemlerde önlem alınmaya çalışılan hata kalıcı hatalardır. Bir takım do-
nanım hataları ise geçici olarak adlandırılmakta ve sadece belirli bir zamanda
oluşup daha sonra kaybolmaktadır. Bu hatalara karşı sıklıkla maliyeti daha az
olan artıklı yürütme yöntemi kullanılmaktadır. Bu yöntem temelde, yapılmak
istenen işlemin birden fazla defa yapılıp elde edilen sonuçların oy çokluğu
prensibine göre oylanarak işlemin beklenen sonucu olarak kabul edilmesidir.
Yöntemin ana fikri, aynı geçici hatanın arka arkaya ve aynı hatalı sonucu ver-
erek oluşması ihtimalinin ihmal edilebilir düzeyde olmasıdır. Özellikle artıklı
ve çoklu iş parçacıklı (redundant multithreading) yöntemler, hataların farklı
çekirdeklerde çalışan kopyalarda eş zamanlı gerçekleşme ihtimalinin daha da
düşük olması sebebiyle yüksek hata toleransı sağlamakta, paralel çalıştırma
sayesinde artıklı çalıştırmanın performans üzerindeki olumsuz etkisinin önüne
geçilmektedir [5, 6].
     Artıklı yürütme yönteminin uygulanması uygulama seviyesinde yer al-
abilmekte ve yazılım geliştiricilere önemli bir miktarda gerçekleme yükü
doğurmaktadır. Artıklı çalıştırılacak bütün işlemlerin bu şekilde gerçeklenmesi
ve gerekli oylama işlemlerinin kodlanması gerekmektedir. Bu çalışmada, bu
gerçekleme yükünü ortadan kaldıracak genel, yeniden kullanılır bir programlama
aracı geliştirmeyi hedefledik. Bu amaçla nesneye yönelik bir programlama or-
tamında GoF (Gang of Four) tasarım örüntülerinden [10] biri olan vekil tasarım
örüntüsünü kullanarak söz konusu gerçekleme yükünün herhangi bir nesne için
otomatik ve saydam olarak yapıldığı, RedundantCaller (artıklı çalıştırıcı) adını
verdiğimiz bir programlama aracı (sınıf) tasarladık.
     Bölüm 2’de bu alandaki ilgili çalışmalar üzerinden kısaca geçilmekte ve bu
bölümü vekil tasarım örüntüsünün özetlendiği Bölüm 3 izlemektedir. Redundant-
Caller aracımızın işleyişinin yeraldığı Bölüm 4’ün ardından aracın neden olduğu
performans düşüşü ve güvenilirlik artışının incelendiği deneysel çalışmaların bu-
lunduğu Bölüm 5 gelmektedir. Bölüm 6 ile makale sonlanmaktadır.


2    İlgili Çalışmalar

Literatürde yazılım tabanlı artıklı çalıştırma için çok sayıda çalışma mevcuttur.
Bu bölümde bu konulardaki çalışmalara yer verilmiştir.
     SRMT (Software-based Redundant Multi-Threading) [7], verilen program ko-
dunu iki iş parçacığına çoklayarak hata tespiti sağlamaktadır. Paralel çalışan
iş parçacıkları, komutların sonuçlarını karşılaştırarak uyuşmazlık durumunda
hata durumu olduğunu tespit etmektedir. Komut seviyesinde sonuç kon-
trolü sağlandığından performansa etkisi oldukça fazladır, o yüzden bunu iy-
ileştirmek için farklı iş parçacıklarının iletişimini sağlayan optimizasyonlar da
önerilmiştir. Detaylı bir derleyici ve yürütme sistemi gerçeklemesi içeren bu
sistem, sadece hata tespiti sağlamakta olup hata toleransı seviyesinin yeniden
yapılandırılmasına imkan vermemektedir.
     RedThreads [8], C/C++ programları için artıklı çok iş parçacıklı çalıştırma
sağlayan bir arayüz sağlamaktadır. Yazılım geliştirici, arayüz tarafından
tanımlanan direktiflerle (directives) programın hangi parçasının, hangi seviyede
(kaç iş parçacığıyla) artıklı çalışacağını belirtebilmektedir. Çalışmada hem der-
leyici, hem de yürütme sistemi gerçeklemesi yapılmış, kullanıcının belirlediği
özelliklere göre artıklı çalıştırma sağlanmıştır. Kullanım kolaylığı açısından Re-
dundantCaller aracımıza benzemekle birlikte C/C++ programlarına yönelik
olması ve çok fazla gerçekleme gerektirmesi yönleriyle bizim çalışmamızdan
farklılık göstermektedir.
     Chen ve Chen [9] yazılım tabanlı artıklı çalıştırma için bir programlama
modeli önermişlerdir. Çalışmalarındaki programlama modeli, hata toleransını
gerçeklemek için çok iş parçacıklı teknikleri kullanmaktadır. Hata düzeltmeyi de
çoğunluk oylamasıyla gerçekleştirmektedir. Ayrıca sistemin cevap vermediği hata
durumları için watchdog zamanlayıcısı kullanılmaktadır. Yazılım geliştiricinin,
yazılımın gerekli yerlerine müdahale etmesi ve programlama modelinin sunduğu
fonksiyonları eklemesi gerekmektedir. Yazılım geliştiriciye saydam bir araç olarak
sunulan RedundantCaller aracını kullanmak için, hata toleransı eklenmek istenen
yazılımda neredeyse hiçbir değişiklik yapılmasına gerek duyulmamaktadır.


3    Vekil Tasarım Örüntüsü

Tasarım örüntüleri nesneye yönelik programlamada çok karşılaşılan tasarım
problemlerine çözüm olarak sunulmuş yeniden kullanılır, esnek, ve doğrulanmış
çözüm önerileridir [10]. Vekil tasarım örüntüsü Eric Gamma ve arkadaşlarının
önerdiği 23 iyi bilinen tasarım örüntüsünden biridir ve şu iki temel probleme
çözüm sunmayı hedeflemektedir:

 – Nesneye erişimi kontrol altına almak
 – Nesneye saydam bir şekilde yeni işlevler kazandırmak




              Şekil 1. Vekil tasarım örüntüsünün UML sınıf şeması [10].
    Temelde hedef olarak seçilen sınıf ile aynı arayüze sahip bir vekil sınıfının
tanımlanması ve vekil sınıfın hedef sınıfı içinde bulundurması (composition)
fikrine dayanır. Hedef sınıf kullanıcıları bu sınıfa vekil sınıf üzerinden erişim
sağlarlar. Şekil 1’de vekil tasarım örüntüsünün UML (Unified Modeling Lan-
guage) sınıf şeması görüntülenmektedir. Vekil tasarım örüntüsü farklı gerçekleme
senaryoları ile yazılım geliştirme alanlarında uygulanmaktadır [11, 12].


4    Vekil Tasarım Örüntüsü Temelli Hata Toleransı
Bu çalışmamızda vekil tasarım örüntüsü temelli RedundantCaller
ismini verdiğimiz saydam bir artıklı çalıştırma aracı geliştirdik
(https://github.com/isil-oz/RedundantCaller). Bunu yaparken Java pro-
gramlama dilindeki dinamik vekil (dynamic proxy) mekanizmasını kullandık.
Bu mekanizma bir arayüz (interface) ile erişilen herhangi bir sınıfa çalıştırma
zamanında otomatik olarak bir vekil sınıf oluşturmak için kullanılmaktadır.
RedundantCaller, verilen herhangi bir sınıfın nesnesi için bu sınıfın metot-
larını artıklı bir şekilde çalıştıracak vekil nesneyi otomatik olarak oluşturur
ve geliştirici bu vekil nesneyi kullanarak gerçeklemek istediği kodu yazar.
RedundantCaller hedef nesnenin artıklı çalıştırılacak bir metodu çağrıldığında
öncelikle o nesnenin artıklı çağırma sayısınca klonunu üretir. Bu işlem Redun-
dantCaller kullanımının getirdiği bir gereksinim olmayıp çağrılan metot nesne
üzerinde değişiklik yapıyor ise sonraki metotların tutarlı ve doğru çalışması
için gereklidir ve artıklı çalıştırma işleminin doğası gereği yapılmaktadır. Daha
sonra, artıklı çalıştırma çok iş parçacıklı (multithreaded) olarak yapılandırılmış
ise oluşturulan hedef nesne klonlarını içeren birer iş parçacığı üretilir ve Java
programlama dilinde eşzamanlı çalıştırma (concurrent execution) için yaygınca
kullanılan Fork-Join mekanizması ile bu iş parçacıkları paralel olarak çalıştırılır.
Tek iş parçacıklı yapılandırma senaryosunda ise bu işlem bir döngü içerisinde
klon nesnelerin metotlarının arka arkaya çalıştırılması şeklinde gerçekleştirilir.
Her iki senaryoda da artıklı çalıştırma neticesinde elde edilen sonuçlar çoğunluk
oylaması yöntemi ile oylanır ve kazanan sonuç işlemin beklenen sonucu olarak
döndürülür. Burada özetlenen bütün bu işlemler geliştiricinin herhangi bir
gerçekleme yapmasını gerektirmeden RedundantCaller nesnesi tarafından say-
dam bir şekilde gerçekleştirilir. RedundantCaller sınıfında yukarıda özetlenen
işleri gerçekleştiren kod parçacığı Kod 1’de listelenmektedir.
     Ayrıca geliştirici, vekil nesne ile erişmek istediği nesnenin arayüz tanımında
artıklı çalıştırmak istediği metotları ve bunların artıklı çalıştırma parametrelerini
belirleyebilir. Metot bazında yapabildiği bu yapılandırma imkanı için yine Java
programlama dilindeki annotation mekanizması kullanılmıştır. Artıklı çalıştırma
yapılandırma parametreleri ihtiyaca göre kolayca arttırılabilmekle beraber bu
çalışmada şu parametrelere yer verilmiştir:
 – votecount : Tamsayı. Metodun kaç defa çalıştırılacağını belirtir.
 – multithreaded : true/false. Artıklı çalıştırma işleminin çok iş parçacıklı
   çalıştırılıp çalıştırılmayacağını belirtir.
                    Kod 1. RedundantCaller artıklı çalıştırma kodu
public O b j e c t i n v o k e ( O b j e c t proxy , Method method , O b j e c t [ ]                args )
    throws Throwable {
    /∗ some i m p l e m e n t a t i o n d e t a i l s ∗/

     if   ( method . i s A n n o t a t i o n P r e s e n t ( RedundantCall . c l a s s ) )
     {
           i n t voteCount = method . g e t A n n o t a t i o n ( RedundantCall . c l a s s ) .
                                           voteCount ( ) ;
           b u i l d T a r g e t C o p i e s ( voteCount ) ;

           boolean m u l t i t h r e a d e d =      method . g e t A n n o t a t i o n ( RedundantCall . c l a s s )
                                                             . multithreaded ( ) ;
           if   ( multithreaded ) {
                  L i s t > l i s t =
                                   redundantRun ( method , a r g s , voteCount ) ;
                  return t h r e a d e d V o t i n g ( l i s t ) ;
           }
           e l s e return s i n g l e T h r e a d e d V o t i n g ( method , a r g s , voteCount ) ;
     }
     e l s e return method . i n v o k e ( t a r g e t , a r g s ) ;
}




          Matrix.java                                            Artıklı Çalışma
      class Matrix{                                        Matrix m = ...;
         Matrix transpose(){...}                           IMatrix i = RedundantCaller.createObject(m);
         Matrix plus(Matrix ){...}                         sonuc = i.transpose();
         ...
         boolean equals(Object ){...}
         int hashCode(){...}
      }



                                                               RedundantCaller
          IMatrix.java                                     Artıklı nesneler yaratılır:
      Interface IMatrix{                                          Matrix m1
         @RedundantCall(voteCount=3,                              Matrix m2
                 multithreaded=true)                              Matrix m3
         Matrix transpose()                                Her bir nesnenin metodunu paralel olarak çalıştırmak için
         @RedundantCall(voteCount=5,                       paralel işler oluşturulur:
                 multithreaded=false)                             Task t1 = m1.transpose
         Matrix plus(Matrix)                                      Task t2 = m2.transpose
      }                                                           Task t3 = m3.transpose
                                                           Paralel olarak artıklı çalıştırma gerçekleştirilir:
                                                                  sonuc1 = t1.invoke
                                                                  sonuc2= t2.invoke
                                                                  sonuc3 = t3.invoke
                                                           Çoğunluk oylaması:
                                                                  sonuc1
                                                                  sonuc2                                  sonuc
                                                                  sonuc3




                              Şekil 2. RedundantCaller ’ın kullanımı.



     RedundantCaller aracımızın kullanım örneği Şekil 2’de bir nesne üzerinde
gösterilmektedir. Örnekte kullanılmak istenen sınıf Matrix sınıfı ve bu sınıfa
erişim için tanımlanan arayüz IMatrix arayüzüdür. Bu arayüz içinde tanımlanan
tüm metotlar için artıklı çalıştırma imkanı sağlanacaktır. Metotlar için belirtilen
annotation aracılığıyla da artıklı çalıştırma yapılandırılabilmektedir. Redundant-
Caller sınıfı, Matrix sınıfına vekillik yapmaktadır. Yazılım geliştirici, istediği
artıklılık seviyesine göre annotationların değerlerini belirleyebilmektedir. Ayrıca
Artıklı Çalışma kutusundaki nesne oluşturma (createObject) satırını yazarak
vekil nesne üzerinden yeni nesne oluşturmaktadır. Şekildeki örnekte trans-
pose metodu için tanımlanan @RedundantCall(voteCount = 3, multithreaded
= true) annotation’ı ile, transpose metodunu 3 iş parçacığıyla artıklı olarak
çalıştırmak istediğimiz belirtilmiştir. plus metodu için tanımlanmış olan @Re-
dundantCall(voteCount = 5, multithreaded = false) annotation’ıyla ise 5 artıklı
çalıştırmanın tek bir iş parçacığıyla gerçekleştirilmesi istenmiştir.


5    Deneysel Çalışma

RedundantCaller aracının nesneye yönelik uygulamaların performans ve
güvenilirlik üzerindeki etkilerini gözlemlemek için gerçekleştirdiğimiz deneyler
bu bölümde yer almaktadır.
     Deneylerimizi temel lineer cebir işlemleri içeren bir paket olan JAMA
kütüphanesini kullanarak gerçekleştirdik [13]. JAMA, Matrix ana sınıfı altında
farklı operasyonlar sunmaktadır. Bu kütüphanenin kullanımı, hata hassasiyeti
ve hata toleransı çalışmalarında [14, 15] sıklıkla kullanılan matris hesaplamaları
içerdiğinden çalışmamız için oldukça uygun olmuştur. Deneylerimizde 1000x1000
boyutunda rastgele değerlere sahip matrisler üreterek Tablo 1’de listelenen temel
31 operasyonu kullandık. Artıklı çalıştırmanın çok iş parçacıklı versiyonlarını
çalıştırabilmek için Intel Xeon E5-2680 temelli çok çekirdekli mimaride deney-
lerimizi çalıştırdık.
     Öncelikle RedundantCaller ’ın performansa olan etkisini gözlemleyebilmek
için deneyler gerçekleştirdik. Bu deneylerde matris operasyonlarının artıklı
çalıştırma olmadan tamamlandığı zamanı, ve artıklı çalıştırmanın tek iş
parçacıklı, 3 iş parçacıklı ve 5 iş parçacıklı versiyonlarının tamamlandığı za-
manları ölçtük. Çalıştırmalar arasındaki eşitsizliklerden kaynaklanabilecek olası
yanıltıcı sonuçlardan etkilenmemek için her bir operasyonu 20 defa çalıştırıp
en yüksek olan bir değeri dışarıda tutarak ortalamalarını hesapladık, ve her
bir operasyonun her bir versiyon için çalıştırma zamanını belirledik. Operasy-
onlar farklı çalıştırma zamanlarına sahip olduğundan ve hepsini tek bir şekilde
göstermek zor olduğundan operasyonları çalıştırma zamanlarına göre üç gruba
ayırarak farklı şekillerde performans sonuçlarını raporladık. Şekil 3 çok kısa
çalıştırma zamanına (normal çalıştırma zamanı 5 saniyeden düşük) sahip op-
erasyonlara ait sonuçları gösterirken, Şekil 5 uzun süreli operasyonlara ait farklı
konfigürasyonlar için operasyonların çalıştırma zamanlarını göstermektedir. Bu
şekillerde performans sonuçları verilen farklı konfigürasyonlar ve açıklamaları
ayrıca Tablo 2’de verilmiştir.
     Şekil 3’te görüldüğü gibi çalıştırma zamanı küçük olan operasyonlar için
artıklı çalıştırma maliyeti oransal olarak çok yüksekken, tek iş parçacıklı (RCSin-
gle) ve üç iş parçacıklı (RC3Thread) üç artıklı çalıştırma konfigürasyonları ben-
           Tablo 1. Deneylerimizde kullandığımız matris operasyonları.

     Operasyon Adı                                Operasyon
    arrayLeftDivide                       Soldan bölme (C = A.\B)
 arrayLeftDivideEquals          Soldan bölüp kendine eşitleme (A = A.\B)
   arrayRightDivide                       Sağdan bölme (C = A./B)
arrayRightDivideEquals          Sağdan bölüp kendine eşitleme (A = A./B)
       arrayTimes                            Çarpma (C = A.*B)
   arrayTimesEquals                 Çarpıp kendine eşitleme (A = A.*B)
            chol                              Cholesky ayrıştırma
           cond                                 Matris durumu
             det                              Matris determinant
             eig                              Özdeğer ayrıştırma
          inverse                                      Ters
              lu                                 LU ayrıştırma
           minus                            Çıkartma (C = A - B)
      minusEquals                  Çıkartıp kendine eşitleme (A = A - B)
          norm1                       1 norm (En büyük sütun toplamı)
          norm2                         2 norm (En büyük tekil değer)
          normF        Frobenius norm (Elemanların karelerinin toplamının karakökü)
         normInf                  Sonsuz norm (En büyük satır toplamı)
            plus                            Toplam (C = A + B)
       plusEquals                 Toplayıp kendine eşitleme (A = A + B)
              qr                                 QR ayrıştırma
            rank                                  Matris rank
           solve                               A*X = B çözümü
     solveTranspose               X*A = B ve ayrıca A’*X’ = B’ çözümü
             svd                            Tekil değer ayrıştırma
          times s                        Skalar ile çarpım (C = s*A)
         times m                   Lineer cebirsel matris çarpımı (A * B)
      timesEquals              Skalar ile çarpıp kendine eşitleme (A = s*A)
           trace                                512, 1024, 2048
        transpose              Matris trace (Diyagonal elemanların toplamı)
          uminus                             Negatifini alma (-A)




               Tablo 2. Karşılaştırma yaptığımız konfigürasyonlar.

         Konfigürasyon Adı                 Konfigürasyon
              NonRC         Normal çalıştırma (Artıklı çalıştırma yok)
             RCSingle         Tek iş parçacıklı, üç artıklı çalıştırma
           RC3Thread          Üç iş parçacıklı, üç artıklı çalıştırma
           RC5Thread         Beş iş parçacıklı, beş artıklı çalıştırma
Şekil 3. Farklı artıklı çalıştırma konfigürasyonları için çalıştırma zamanları (kısa süreli
operasyonlar için).
zer sonuçlar vermektedir. Bu durumlarda beş iş parçacıklı, beş artıklı çalıştırma
(RC5Thread) konfigürasyonunun maliyeti 10-20 kata kadar çıkmaktadır. Bu
gruptaki operasyonların çalıştırma zamanlarının çok kısa olmasından dolayı;
artıklı çalıştırmadaki nesnelerin klonlanması, çoğunluk oylaması gibi fazladan
çalıştırma haricindeki işlemlerin zamanının normal çalıştırma zamanının çok
fazla üstüne çıkmasına sebep olmaktadır. Özellikle paralel versiyonlarda iş
parçacıklarının yaratılması ve yönetilmesi işlerinin de eklenmesiyle çalıştırma
zamanları göreceli olarak çok artmaktadır. Örneğin, çalıştırılması 2 saniye süren
bir operasyonu üç iş parçacıklı, üç artıklı çalıştırma ile çalıştırdığımızı düşünelim.
Bir iş parçacığı yaratma işlemi 0,5 saniye sürüyorsa, sadece iş parçacığı
yaratma işleminin eklenmesiyle operasyonun çalıştırma zamanı yaklaşık 2
katına çıkmaktadır. Bu durumu gözlemleyebilmek için artıklı çalıştırma kon-




Şekil 4. Farklı artıklı çalıştırma konfigürasyonları için arrayLeftDivide operasyonunun
çalıştırma zamanının dağılımı.
Şekil 5. Farklı artıklı çalıştırma konfigürasyonları için çalıştırma zamanları (uzun süreli
operasyonlar için).
figürasyonları için işlem seviyesinde zaman ölçümleri yaptık. Şekil 4, nor-
mal çalışması 3-4 saniye süren arrayLeftDivide operasyonunun çalıştırma za-
manının hangi işlemlerde geçtiğini göstermektedir. Diğer operasyonlar için de
benzer durumlar söz konusudur. Öte yandan, Şekil 5’te görüldüğü gibi nor-
mal çalışması 1000-10000 saniye süren bir uygulama için artıklı çalıştırmanın
fazladan çalıştırma haricindeki işlemleri görece çok kısa olduğundan, artıklı
çalıştırmanın toplam maliyeti oldukça düşük olmaktadır. Tek iş parçacıklı kon-
figürasyonda (RCSingle), üç artıklı çalıştırma tek bir iş parçacığı tarafından arka
arkaya yapıldığı için onun performansı en kötüyken; paralel konfigürasyonlarda
(RC3Thread ve RC5Thread) üç-beş iş parçacığı, artıklı çalıştırmaları farklı
çekirdeklerde eş zamanlı olarak gerçekleştirdiğinden toplam çalıştırma zamanları
ciddi artış göstermemektedir. Uzun hesaplamalarda fazladan çalıştırma haricin-
deki işlemlerin maliyeti görünmemekte ve asıl büyük hesaplama iş parçacıklarına
yaptırıldığı için maliyet gizli kalmış olmaktadır.

    RedundantCaller ’ın   performansının  yanı    sıra   hata      kapsamını
gözlemleyebilmek için hata enjeksiyonu deneyleri gerçekleştirdik. Bunun
için deneylerde kullandığımız Matrix sınıfı için operasyon seviyesinde belirli
bir ihtimalle hesaplama hata durumları oluşturduk, normal çalıştırmanın
ve artıklı çalıştırmanın hesapladığı değerin hesaplaması gereken değere eşit
olup olmadığını kontrol ederek sessiz veri bozulumu (silent data corruption)
durumlarını tespit etmeye çalıştık. Hata enjeksiyonu deneyleri uzun zaman
aldığından nispeten kısa çalıştırma zamanlarına sahip transpose, norm1,
norm2, ve uminus operasyonlarına hata enjeksiyonu yaptık. RedundantCaller
aracı açısından farklılık oluşturmadığı için bu operasyon alt kümesinin yeterli
olduğunu düşünmekteyiz. Her bir operasyon için 1000 farklı çalıştırma yaparak
normal çalıştırmanın ve artıklı çalıştırmanın hatalı hesaplama durumlarını
gözlemlemeye çalıştık. İlk olarak literatürde de olası hata oranı olarak tespit
edilen 0,001 değeriyle hata enjeksiyon testleri çalıştırdık. Bu hata değeriyle
normal çalıştırma için 0,002 (4000 çalıştırmada 8 hatalı veri hesaplama) veri
bozulumu oranı gözlemlerken üç artıklı çalıştırmada herhangi bir veri bozulması
ile karşılaşmadık. Hata oranını 0,01, 0,1, 0,2 gibi daha az gerçekçi değerlere
değiştirdiğimizde normal çalıştırmanın veri bozulumu oranı artış gösterirken,
üç artıklı çalıştırmada veri bozulumu oranı sıfırda kalarak %100 hata kapsamı
gözlemlenmiştir. Hata analizi deneylerimiz, çoğunluk oylaması temelli hata
toleransı sistemlerindeki beklenen hata kapsamı seviyesini doğrulamıştır.
Deney sonuçlarımız, aracımızın tanımlanan hata modelindeki hata kapsamı
performansını göstermektedir.


6    Sonuç

Bilgisayarların ve üzerinde yürütülen yazılımların hatasız ve güvenilir çalışması,
çoğu zaman performans ve maliyet gibi diğer birçok kriterin önüne geçmekte
ve bilgi sistemlerinin tasarım kararlarında önemli bir rol oynamaktadır.
Geliştiriciler yazılımları oluştururken çözmek istedikleri orjinal problemin yanı
sıra, yazılımın daha güvenilir olması için almaları gereken tedbirleri de göz
önünde bulundurmak durumundadırlar. Çoğu kez bu tedbirler yüksek miktarda
ilave kod karmaşıklığı ve/veya performans yükü doğurmaktadır.
     Bu çalışmada nesne yönelimli programlamada yaygınca kullanılan vekil
tasarım örüntüsünü kullanarak geliştiricilere güvenilir yazılım mekaniz-
malarından biri olan artıklı çalıştırma tekniğini esnek, saydam ve otomatik
bir şekilde sunan bir geliştirme aracı oluşturduk. Vekil tasarım örüntüsünün
diğer kullanım alanlarının yanında bu alanda da etkin bir çözüm olarak kul-
lanılabileceğini göstermiş olduk. Java programlama dilinin sunduğu dinamik
vekil ve annotation dil öğelerini kullanarak tasarladığımız aracı genel ve ko-
layca yapılandırılabilir bir şekilde gerçekledik. Yine Java’da yaygınca kullanılan
fork-join sistemi ile artıklı çalıştırma işinin isteğe bağlı olarak çok iş parçacıklı
olarak yapılmasını sağladık.
     Örnek bir Java kütüphanesi ile gerçekleştirdiğimiz deneylerde paralel
çalıştırmanın sağladığı fayda ile aracımızın küçük bir performans kaybı ile
önemli oranlarda güvenilirlik artışı sağladığını gösterdik. Yine deneyler için
oluşturduğumuz test kodunda RedundantCaller kullanımının mevcut kodu min-
imum miktarda değiştirdiğini ve geliştiriciye ihmal edilebilir miktarda bir
ilave iş yükü getirdiğini gözlemledik. Ayrıca önerdiğimiz aracın benzer pro-
gramlama öğelerinin (dynamic proxy, annotation) desteklendiği diğer nesneye
yönelik programlama dillerinde (C#, C++ vb.) de kolaylıkla gerçeklenebileceğini
düşünmekteyiz.


7   Teşekkür

Bu çalışmada kullanılan hesaplama kaynakları Ulusal Yüksek Başarımlı
Hesaplama Merkezi’nin (UHeM), 1005202018 numaralı desteğiyle, sağlanmıştır.


Kaynaklar
1. Israel Koren, C. Mani Krishna: Fault-Tolerant Systems, Morgan Kaufmann, (2007).
2. George A. Reis, Jonathan Chang, Neil Vachharajani, Ram Rangan, David I. August:
   Swift: Software implemented fault tolerance, International Symposium on Code
   Generation and Optimization, (2005).
3. George A. Reis, Jonathan Chang, Neil Vachharajani, Ram Rangan, David I. August,
   Shubhendu S. Mukherjee: Design and evaluation of hybrid fault-detection systems.
   International symposium on Computer Architecture (ISCA), (2005).
4. Alex Shye, Joseph Blomstedt, Tipp Moseley, Vijay Janapa Reddi, Daniel a. Connors:
   Plr: A software approach to transient fault tolerance for multicore architectures.
   IEEE Transactions on Dependable and Secure Computing, 6(2):135–148, (2009).
5. S. S. Mukherjee, M. Kontz, S. K. Reinhardt: Detailed design and evaluation of re-
   dundant multi-threading alternatives, International Symposium on Computer Ar-
   chitecture (ISCA), (2002).
6. M. Gomaa, C. Scarbrough, T. N. Vijaykumar, I. Pomeranz: Transient-fault recov-
   ery for chip multiprocessors, International Symposium on Computer Architecture
   (ISCA), (2003).
7. Cheng Wang, Ho seop Kim, Youfeng Wu, Victor Ying: Compiler-Managed Software-
   based Redundant Multi-Threading for Transient Fault Detection,International Sym-
   posium on Code Generation and Optimization (CGO), (2007).
8. Saurabh Hukerikar, Keita Teranishi, Pedro C. Diniz, Robert F. Lucas: RedThreads:
   An Interface for Application-Level Fault Detection/Correction Through Adaptive
   Redundant Multithreading, International Journal of Parallel Programming, 46:225-
   251, (2018).
9. Yi-Shen Chen, Peng-Sheng Chen: A Software-Based Redundant Execution Pro-
   gramming Model for Transient Fault Detection and Correction, 45th International
   Conference on Parallel Processing Workshops (ICPPW), (2016).
10. Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides: Design Pat-
   terns:Elements of Reusable Object-Oriented Software, Addison-Wesley, (1994).
11. K. Soundararajan and R.W. Brennan: A Proxy Design Pattern to Support Real-
   Time Distributed Control System Benchmarking, Holonic and Multi-Agent Systems
   for Manufacturing (HoloMAS), (2005).
12. K. Soundararajan and R.W. Brennan: Design patterns for real-time distributed
   control system benchmarking, Robotics and Computer-Integrated Manufacturing,
   24, 5:606-615, (2008).
13. JAMA Homepage, https://math.nist.gov/javanumerics/jama/. Last accessed 11
   June 2018.
14. Greg Bronevetsky and Bronis R. de Supinski: Soft Error Vulnerability of Iterative
   Linear Algebra Methods, International conference on Supercomputing (ICS), (2008).
15. Konrad Malkowski, Padma Raghavan, Mahmut Kandemir: Analyzing the soft error
   resilience of linear solvers on multicore multiprocessors, International Symposium
   on Parallel and Distributed Processing (IPDPS), (2010).