ForkJoin Framework - paralel programlama

java
  • Turgay Can
  • Tarih

    05 Jul, 2013
  • Yorum

    0
  • Görüntüleme

    2148
  • İndirme

    0

ForkJoin Framework - paralel programlama

Fork-Join Framework nedir?

For-Join bir problemi küçük parçalara bölerek, onları paralel olarak eş zamanlı çözmek ve nihayetinde birleştirerek sonuca ulaşma yaklaşımı baz alınrak geliştirilmiş ramework(çatı)'tür.

JDK 5 içindede mevcuttu, JDK 7'dede mevcut bir framework'tür. Framework'ün gerçek anlamda performanslı çalışması için yüksek sayıda (10larca,yüzlerce) işlemci çekirdeğinin olması gerekiyor. Çünkü multi-core(çok çekirdek) sistemler için dizayn edilmiştir. Genel olarak, 4 çekirdek ve üzeri sistemlerde performans olarak kısmen göze çarpabilir bu ise yapılacak işe göre değişkenlik gösterir.

Aşağıdaki 4 sınıf bu framework için önem taşıyor.

ForkJoinPool
RecursiveTask
ForkJoinTask
RecursiveAction

ForkJoinPool -> sınıfı java.util.concurrent paketi içindeki AbstractExecutorService abstract sınıfından kalıtım almaktadır ve AbstractExecutorService sınıfı ise ExecutorService arayüz sınıfından implement etmektedir. ExecutorService alt sınıf olarak Executer arayüz sınıfı kullanmaktadır ve bu sınıf için void execute(Runnable command); metodunu işliyor. Bu metod Runnable olduğu için sürekli çalışır (work-stealing) olarak devam ediyor.

ForkJoinPool genellikle hesaplama ile değiştirilmiş ya da bir değer döndürme gibi alt problemler üzerinde kullanılabilir.
Bu durumları ForkJoin ile üstesinden gelmek daha performanslı olduğu iddia ediliyor(Test çalışmaları sonucunda).

ForkJoinTask -> ForkJoin Pool içinde soyut bir sınıftan türemiş task olarak çalışır. Lightwieght(Hafif) thread(işlem parçacıkları) lerden oluşur ve bazı thread'lerin imitasyonları vardır. Birden çok sayıda yeni tasklar oluşturmak için fork() ve join.fork() metodlarını kullanır. join.fork() taskı bitmesini bekler fork'un böyle bir limitasyonu yoktur.

Örneğin eğer bir değer dönüyorsa işlem sonrası java.util.concurrent.RecursiveTask sınıfından türemiş sınıflar kullanılır. Diğer durumlar için ise;
java.util.concurrent.RecursiveAction sınıfından kalıtım almış sınıflar kullanılır.

Bir örnek implementasyon senaryosu düşünelim. Her alt sınıf bir değer döndürsün ve bu değerleri ForkJoin çatısı ile kullanalım.

Mesela Yüksek sayıda bir işlemin hesaplanması, fikir vermesi açısından örneğimiz bağdaştırılabilir.

Fibonacci sayısının hesaplanması

Tek bir Main Thread ile ;

import java.text.DateFormat;
import java.text.SimpleDateFormat;

/**
 *
 * @author turgay.can
 */
public class FibForkJoin {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        DateFormat df = new SimpleDateFormat("mm:ss");        
        long startTime = System.currentTimeMillis();
        System.out.println("Başlangıç : " + startTime);
        for (int i = 0; i < 50; i++) {
            System.out.println(i + " : " + doFib(i));
        }
        long finishTime = System.currentTimeMillis();
        System.out.println("İşlem Süresi : " + df.format((finishTime - startTime)));

    }

    static long doFib(int i) {
        if (i == 0 || i == 1) {
            return 1;
        } else {
            return doFib(i - 1) + doFib(i - 2);
        }

    }
}

Çıktı :

Başlangıç : 1369983753665
0 : 1
1 : 1
2 : 2
3 : 3
...
20 : 10946
21 : 17711
..
.
48 : 7778742049
49 : 12586269025
İşlem Süresi : 01:44

ForkJoin Paralel Task

public static void main(String[] args) {
        // TODO code application logic here
        DateFormat df = new SimpleDateFormat("mm:ss");

        ForkJoinPool forkJoinPool = new ForkJoinPool();

        long startTime = System.currentTimeMillis();
        long result =
                forkJoinPool.invoke(new FibForkJoin(0, 100));
        long finishTime = System.currentTimeMillis();
        System.out.println("İşlem Süresi : " + df.format((finishTime - startTime)));

    }


private int from;
    private int to;

    public FibForkJoin(int from, int to) {
        this.from = from;
        this.to = to;
    }

    @Override
    protected Long compute() {
        long sum = 0L;
        int mid = (to + from) >>> 1;
        System.out.println("mid : " + mid);
        if ((to - from) < 41) {
            for (int i = from; i < to; i++) {
                System.out.println(i + " : " + doFib(i));
            }
            return sum;
        } else {
            System.out.println("here");
            List> forks =
                    new ArrayList<>();
            FibForkJoin task1 =
                    new FibForkJoin(from, mid);
            FibForkJoin task2 =
                    new FibForkJoin(mid, to);
            forks.add(task1);
            task1.fork();
            forks.add(task2);
            task2.fork();
            for (RecursiveTask task : forks) {
                sum += task.join();
            }
            return sum;
        }
    }

Çıktı:

Başlangıç : 1373013790476
0 : 1
1 : 1
2 : 2
3 : 3
...
48 : 7778742049
49 : 12586269025
İşlem Süresi : 01:45

0 Yorum..

Yorum yapmak için "Giriş yapın" yada "Misafir üye" olarak yorum yapabilirsiniz.

Yorum Yap