2010-08-19 10 views

risposta

4
+0

ho cercato di spiegare in modo approfondito qui: [Java: utilizzando la forcella/Accedi Quadro per la risoluzione in parallelo del divide et impera problemi] (http://www.davismol.net/2016/ 01/24/java-using-the-forkjoin-framework-per-la-parallela-risoluzione-di-divide-e-conquista-problemi /) –

2

Diciamo che avete un insieme di cose che devono essere elaborati. Hai un numero di thread in grado di afferrare sottoinsiemi di questa raccolta ed elaborarli. Lo fanno tutti contemporaneamente (la parte della forcella) quindi aspettano che l'ultimo finisca (la parte di join) prima di tornare.

+0

Con il priviso che il genitore corrente _stompa eseguendo_ fino al completamento di tutti gli operatori concorrenti, e _then_ riprende. So che questo era inerente alla tua descrizione, ma penso che valga la pena di essere molto esplicito perché questo è tutto ciò che lo rende davvero diverso da qualsiasi altro tipo di parallelismo esplicito. – Gian

+0

Beh, non è un fork di operazioni, eseguirle tutte e poi unirle. È un approccio divide et impera. –

8

Fork Join è un nuovo framework che ha un'API più facile da usare per un algoritmo parallelo, divide e conquista.

Supponiamo di avere un'attività a esecuzione prolungata che, per questa istanza, ha un algoritmo complicato. Si consiglia di eseguire il fork delle attività di grandi dimensioni e ora lavorare su queste due attività. Ora diciamo che quei due compiti sono ancora troppo grandi, li si forchetta in due compiti (a questo punto ce ne sono quattro).

Si continuerà fino a quando ogni attività ha una dimensione accettabile e si richiama l'algoritmo. È importante sapere che l'invocazione di ciascuna attività viene eseguita in parallelo. Quando l'attività è completata, viene unita all'altra attività con cui è stata biforcata e consolidata i risultati.

Continuerà fino a quando tutte le attività sono state unite e viene restituita un'attività.

3

Oltre a ciò che è stato già detto, fork/join utilizza il furto del lavoro: i thread che finiscono per rubare le attività da altri thread ancora occupati. Ed ecco un esempio che può aiutare a capire come FJ può essere utilizzato:

public class SumCounter extends RecursiveTask<Long> { 

    private final Node node; 

    public SumCounter(Node node) { 
    this.node = node; 
    } 

    @Override 
    protected Long compute() { 
    long sum = node.getValue(); 
    List<ValueSumCounter> subTasks = new LinkedList<>(); 

    for(Node child : node.getChildren()) { 
     SumCounter task = new SumCounter(child); 
     task.fork(); // run asynchronously 
     subTasks.add(task); 
    } 

    for(SumCounter task : subTasks) { 
     sum += task.join(); // wait for the result 
    } 

    return sum; 
    } 

    public static void main(String[] args) { 
    Node root = getRootNode(); 
    new ForkJoinPool().invoke(new SumCounter(root)); 
    } 

} 
1

Let ho appena messo i miei due centesimi per fare una comprensione di base di Fork/Join simple.

What is Fork/Join? 

The fork/join framework is an implementation of the ExecutorService interface 
that helps you take advantage of multiple processors. It is designed for work 
that can be broken into smaller pieces recursively. The goal is to use all the 
available processing power to enhance the performance of your application. 
  • Tale quadro è molto utile per la modellazione divide et impera problemi. Questo approccio è adatto per attività che possono essere suddivise in modo ricorsivo e calcolate su scala più piccola; i risultati calcolati sono quindi combinati.
  • Il framework è un'implementazione dell'interfaccia ExecutorService e fornisce una piattaforma concorrente di facile utilizzo per sfruttare i processori multipli .

Termine utile per questo quadro

  • Forking: Dividendo il compito in piccoli compiti è forking.
  • dell'adesione: Unire i risultati dei compiti più piccoli si unisce

Come con qualsiasi implementazione ExecutorService, la forcella/join quadro distribuisce compiti a thread di lavoro in un pool di thread. Il framework fork/join è distinto perché utilizza un algoritmo per il furto del lavoro. I thread di lavoro che esauriscono le cose da fare possono rubare le attività da altri thread ancora occupati.

Il Fork/Join algoritmo è stato progettato come segue:

  • compiti divisi
  • forchetta compiti
  • unire i compiti
  • comporre i risultati
doRecursiveTask(input){ 
    if(task is small enough to handled by a thread){ 
     compute the small task; 
     if there is result to return, then do so 
    }else{ 
     divide the task i.e, fork() into two parts 
     call compute on first task, join on second task, combine both results and return 
    } 
} 

Che cos'è l'algoritmo di furto del lavoro?

Ogni thread di lavoro nel Fork/Join quadro ha una coda di lavoro, che viene implementato utilizzando un Deque. Ogni volta che viene creata una nuova attività (o attività secondaria), , viene inviata all'inizio della propria coda. Quando un'attività completa un'attività ed esegue un join con un'altra attività che non è ancora completata con lo , funziona in modo intelligente. Il thread apre una nuova attività dal capo della coda e avvia l'esecuzione anziché il sonno (nell'ordine attendere che venga completata un'altra attività). In effetti, se la coda di un thread è vuota, il thread apre un'attività dalla coda della coda che appartiene a un altro thread. Questo non è altro che un algoritmo per il furto del lavoro. More detail is here