Tenga en cuenta la siguiente secuencia de comandos shell:Estrategias para tuberías concurrentes en Java
gzip -dc in.gz | sed -e 's/@/_at_/g' | gzip -c > out.gz
Este tiene tres procesos que trabajan en paralelo para descomprimir una corriente, modificarlo, y volver a comprimirlo. Ejecutando time
Veo que el tiempo de mi usuario es aproximadamente el doble que el de mi tiempo real, lo que indica que el programa funciona efectivamente en paralelo.
He intentado crear el mismo programa en Java colocando cada tarea en su propio hilo. Desafortunadamente, el programa Java multiproceso es solo aproximadamente 30% faster que la versión single threaded para la muestra anterior. Intenté usar un Exchanger y un ConcurrentLinkedQueue. La cola vinculada a ConcurrentLinkedQueue causa mucha controversia, aunque los tres hilos generalmente se mantienen ocupados. El Intercambiador tiene menor contención, pero es más complicado, y no parece mantener al trabajador más lento ejecutándose el 100% del tiempo.
Estoy tratando de encontrar una solución pura de Java para este problema sin mirar uno de los marcos de tejido de bytes o un MPI basado en JNI.
La mayor parte de la investigación concurrente y las API se refieren a sí mismos con los algoritmos divide-and-conquer, dando a cada trabajo del nodo que es ortogonal y no dependiente en los cálculos anteriores. Otro enfoque de concurrencia es el enfoque de canalización, donde cada trabajador hace un trabajo y pasa los datos al siguiente trabajador.
No estoy tratando de encontrar la forma más eficiente de extraer un archivo gzip'd, sino más bien estoy buscando cómo descomponer eficientemente las tareas en una tubería, a fin de reducir el tiempo de ejecución al de la la tarea más lenta.
tiempos actuales de un archivo de línea de 10 metros son los siguientes:
Testing via shell
real 0m31.848s
user 0m58.946s
sys 0m1.694s
Testing SerialTest
real 0m59.997s
user 0m59.263s
sys 0m1.121s
Testing ParallelExchangerTest
real 0m41.573s
user 1m3.436s
sys 0m1.830s
Testing ConcurrentQueueTest
real 0m44.626s
user 1m24.231s
sys 0m10.856s
Estoy ofreciendo una recompensa por una mejora del 10% en Java, medida por el tiempo real en un sistema de cuatro núcleos con filas de 10m datos de prueba. Las fuentes actuales están disponibles en Bitbucket.
Un ejemplo de código de lo que está haciendo en Java sería muy útil para ofrecer mejoras. Es difícil ver lo que ha intentado –
Siga los enlaces. – dmeister
¿Está probando en una máquina con varias CPU? No estoy seguro si la JVM puede usar más de 1 CPU. –