¿La programación concurrente es más agrupada o agrupada?

Estoy tratando de entender mi cerebro en torno a la programación paralela / concurrente (en Java) y estoy obsesionado con algunos fundamentos que no parecen estar cubiertos en ninguno de los tutoriales que he estado leyendo.

Cuando hablamos de "subprocesos múltiples" o "programación paralela / concurrente", ¿eso significa que estamos tomando un gran problema y lo estamos extendiendo en muchos subprocesos, o primero lo estamos descomponiendo explícitamente en subproblemas más pequeños y pasamos cada subproblema a su propio hilo?

Por ejemplo, digamos que sí EndWorldHungerTask implements Runnable, y la tarea logra un problema enorme. Para completar su objetivo, tiene que hacer un trabajo realmente pesado, digamos, cien millones de veces:

public class EndWorldHungerTask implements Runnable {

    public void run() {
        for(int i = 0; i < 100000000; i++)
            someReallyExpensiveOperation();
    }
}

Para hacer esto "concurrente" o "multiproceso", pasaríamos esto EndWorldHungerTaska, digamos, 100 subprocesos de trabajo (donde la JVM le dice a cada uno de los 100 trabajadores cuándo debe estar activo y trabajar en la próxima iteración / someReallyExpensiveOperation()llamada ), ¿o lo refactorizaríamos de forma manual / explícita para que cada uno de los 100 trabajadores esté iterando sobre diferentes partes del bucle / trabajo por hacer? En ambos casos, cada uno de los 100 trabajadores solo está iterando un millón de veces.

Pero, bajo el primer paradigma, Java le dice a cada subproceso cuándo ejecutar. Bajo el segundo, el desarrollador necesita particionar manualmente (en el código) el problema con anticipación y asignar cada subproblema a un nuevo subproceso.

Supongo que estoy preguntando cómo se hace "normalmente" en tierra Java. Y, no solo por este problema, sino en general.

Respuesta 1

Supongo que estoy preguntando cómo se hace "normalmente" en tierra Java. Y, no solo por este problema, sino en general.

Esto depende en gran medida de la tarea en cuestión.

El paradigma estándar en Java es que usted mismo debe dividir el trabajo en fragmentos. Distribuir esos fragmentos en varios subprocesos / núcleos es un problema separado, y existe una variedad de patrones para eso (colas, grupos de subprocesos, etc.).

Es interesante observar que existen marcos que pueden utilizar automáticamente múltiples núcleos para ejecutar cosas como forbucles en paralelo (por ejemplo, OpenMP ). Sin embargo, no conozco ninguno de estos marcos para Java.

Finalmente, podría darse el caso de que la biblioteca de bajo nivel que realiza la mayor parte del trabajo pueda utilizar múltiples núcleos. En tal caso, el código de nivel superior puede permanecer un solo subproceso y aún beneficiarse del hardware multinúcleo. Un ejemplo podría ser el código numérico usando MKL debajo de las cubiertas.

Respuesta: 2

Cuando hablamos de "subprocesos múltiples" o "programación paralela / concurrente", ¿eso significa que estamos tomando un gran problema y lo estamos extendiendo en muchos subprocesos, o primero lo estamos descomponiendo explícitamente en subproblemas más pequeños y pasamos cada subproblema a su propio hilo?

Creo que esto depende en gran medida del problema. Hay momentos en los que tiene la misma tarea a la que llama 1000 o millones de veces con el mismo código. Este es el ExecutorSerivce.submit()tipo de patrón. Tiene millones de líneas de un archivo y está ejecutando algunos métodos de procesamiento en cada línea. Supongo que este es su tipo de problema "difundirlo en muchos hilos". Esto funciona para modelos de hilos simples.

Pero hay otros casos en los que el espacio del problema se compone de una gran cantidad de tareas no homogéneas. A veces puede generar un solo subproceso para manejar algo de mantenimiento de fondo, y otras veces un grupo de subprocesos aquí y allá para procesar alguna cola de trabajo. Normalmente, cuanto mayor es el alcance del problema, más complicado es el modelo de simultaneidad y se utilizan más tipos diferentes de agrupaciones e hilos. Supongo que este es el tipo de "descomponerlo en subproblemas más pequeños".

Para hacer este "concurrente" o "multihilo", pasaríamos esta EndWorldHungerTask a, por ejemplo, 100 hilos de trabajo (donde la JVM le dice a cada uno de los 100 trabajadores cuándo debe estar activo y trabajar en la próxima iteración / someReallyExpensiveOperation () call), ¿o lo refactorizaríamos de forma manual / explícita para que cada uno de los 100 trabajadores esté iterando sobre diferentes partes del bucle / trabajo por hacer? En ambos casos, cada uno de los 100 trabajadores solo está iterando un millón de veces.

En su caso, no veo cómo puede resolver el hambre en el mundo (para usar su analogía) con un conjunto de código de hilo. Creo que hay que "descomponerlo en subproblemas menores", que corresponde al último caso que explico anteriormente: una serie completa de subprocesos que ejecutan un código diferente. Algunas de las soluciones secundarias se pueden hacer en grupos de subprocesos y otras se realizarán con subprocesos individuales, cada uno con un código separado.

Supongo que estoy preguntando cómo se hace "normalmente" en tierra Java. Y, no solo por este problema, sino en general.

"Normalmente" depende en gran medida del problema y su complejidad. En mi experiencia, normalmente uso las ExecutorServiceconstrucciones tanto como sea posible. Pero con cualquier problema de tamaño decente, se encontrará con varios grupos de subprocesos diferentes, subprocesos Spring timer, tareas personalizadas de subprocesos únicos, modelos de productor / consumidor, etc., etc.

Respuesta: 3

Normalmente, desearía que cada subproceso ejecutara una tarea desde el inicio hasta el final, no ganaría nada si dejara la tarea a la mitad, luego detuviera la ejecución en ese subproceso y "llamara" a otro subproceso para finalizar el trabajo. Java ofrece, por supuesto, herramientas para este tipo de sincronización de subprocesos, pero realmente se usan cuando una tarea depende de otra tarea para completar, no para que otro subproceso pueda completar la tarea.

La mayoría de las veces tendrá un gran problema, que consiste en varias tareas, si estas tareas se pueden ejecutar simultáneamente, tendría sentido generar hilos para ejecutar estas tareas. Hay una sobrecarga asociada con la creación de subprocesos, por lo que si todas las tareas son secuenciales y deben esperar a que finalice el otro, entonces no sería beneficioso generar múltiples subprocesos, solo un subproceso para que no bloquee el subproceso principal .

Respuesta: 4

Después de esta respuesta sobre cómo imprimir un texto predefinido antes y después de una JTable (no encabezado y pie de página), quiero ir más allá. Con la clase Libro, es posible, como el ejemplo, imprimir ...

¿Cómo se puede especificar un paso para JSpinner? (por ejemplo, de 10 minutos en lugar de 1) Hay un modelo que permite seleccionar el tamaño del paso para los números SpinnerNumberModel (valor, min, max, step); pero como ...

Estoy ejecutando Glassfish 3.1.2 integrado en la unidad de prueba de mi aplicación. Configuré un ScatteredArchive como este: archive.addClassPath (nuevo archivo ("target / classes")); archive.addClassPath (nuevo archivo ("src / test / ...

Sé que esta es una pregunta común, pero he estado buscando e he incluido la clase en eclipse a través del buildpath. Empiezo a escribir la declaración de importación y autocompleta opciones para mí ...