2010-08-19 22 views

Respuesta

4
+0

he tratado de explicar en profundidad aquí: [Java: utilizando el Tenedor/Join Marco para la resolución paralela de divide y vencerás problemas] (http://www.davismol.net/2016/ 01/24/java-using-the-forkjoin-framework-for-the-parallel-resolution-of-divide-and-conquer-problems /) –

2

Digamos que tiene una colección de cosas que necesitan ser procesados. Tienes varios hilos que pueden tomar subconjuntos de esta colección y procesarlos. Todos hacen esto concurrentemente (la parte de la horquilla) y luego esperan en la última para terminar (la parte de la unión) antes de regresar.

+0

Con el priviso que el padre actual _restaura ejecutando_ hasta que todos los trabajadores concurrentes terminen, y _then_ reanuda. Sé que esto fue inherente a su descripción, pero creo que vale la pena ser muy explícito porque eso es todo lo que realmente hace que esto difiera de cualquier otro tipo de paralelismo explícito. – Gian

+0

Bueno, no es una carga de operaciones, realice todas y luego únase. Es un enfoque de dividir y vencer. –

8

Fork Join es un nuevo marco que tiene una API más fácil de usar para un algoritmo paralelo, dividir y conquistar.

Digamos que tiene una tarea larga que, para esta instancia, tiene un algoritmo complicado. Querrá dividir las tareas grandes y ahora trabajar en esas dos tareas. Ahora digamos que esas dos tareas son todavía demasiado grandes, dividiría cada una en dos tareas (en este punto hay cuatro).

Continuará esto hasta que cada tarea tenga un tamaño aceptable e invoque el algoritmo. Es importante saber que la invocación de cada tarea se realiza en paralelo. Cuando la tarea se completa, se une con la otra tarea con la que se bifurcó y consolida los resultados.

Esto continuará hasta que todas las tareas se hayan unido y se haya devuelto una tarea.

3

Además de lo que ya se ha dicho, fork/join utiliza robo de trabajo: los hilos que se quedan sin cosas que hacer pueden robar tareas de otros hilos que todavía están ocupados. Y aquí es un ejemplo que puede ayudar a entender cómo FJ se puede utilizar:

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 simplemente pongo mis dos centavos para hacer que la comprensión básica de Fork/Join sea 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. 
  • Este marco es muy útil para el modelado de divide y vencerás problemas. Este enfoque es adecuado para tareas que se pueden dividir de forma recursiva y se pueden calcular en una escala menor; los resultados calculados son y luego combinados.
  • El marco es una implementación de la interfaz ExecutorService y proporciona una plataforma simultánea fácil de usar para explotar procesadores múltiples.

término útil para este marco

  • bifurca: Dividir la tarea en tareas más pequeñas se bifurcan.
  • Unión: La fusión de los resultados de las tareas más pequeñas se une a

Como con cualquier aplicación ExecutorService, el tenedor/unirse marco distribuye tareas a los subprocesos de trabajo en un grupo de subprocesos. El marco fork/join es distinto porque utiliza un algoritmo de robo de trabajo. Los subprocesos de trabajo que se quedan sin cosas que hacer pueden robar tareas de otros subprocesos que todavía están ocupados.

El Tenedor/Join algoritmo está diseñado de la siguiente manera:

  • tareas divididas
  • tenedor las tareas
  • unirse a las tareas
  • componer los resultados
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 
    } 
} 

¿Qué es el algoritmo de robo de trabajo?

Cada subproceso de trabajo en el Tenedor/Join marco tiene una cola de trabajo, que se implementa utilizando un deque. Cada vez que se crea una nueva tarea (o subtarea) , se lleva al encabezado de su propia cola. Cuando una tarea completa una tarea y ejecuta una unión con otra tarea que no está completada, , funciona de manera inteligente. El hilo muestra una nueva tarea desde el encabezado de su cola y comienza a ejecutarse en lugar de suspender (en orden para esperar a que se complete otra tarea). De hecho, si la cola de un subproceso está vacía, el subproceso muestra una tarea desde el final de la cola que pertenece a otro subproceso. Esto no es más que un algoritmo de robo de trabajo. More detail is here