A medida que la informática ha avanzado, he pasado de 1 núcleo a 2 núcleos, a 4 núcleos... a 64 subprocesos en mi estación de trabajo. Mientras tanto, .jsl se ha mantenido efectivamente como un solo subproceso. Sé que algunas plataformas utilizarán todos los subprocesos, pero me gustaría poder distribuir operaciones jsl simples a voluntad en varios subprocesos. Por ejemplo, si tengo un script que opera por filas en 10.000.000 de filas de datos, si estoy iterando por fila en un bucle for y sé que el resultado de cada fila es independiente de las otras filas, me gustaría dividir eso. operación en 64 bucles for asíncronos, pausar otras ejecuciones mientras los 64 bucles se completan en paralelo, luego volver a un script sincrónico de un solo subproceso después de que todos estén completos, muy parecido a lo que haría en .py con Pool() y poolObject.join.
Hola Steve,
Hay muchos lugares en JMP donde intentamos aprovechar múltiples núcleos: todo, desde guardar/abrir una tabla de datos comprimidos (cada columna se envía a un hilo diferente), hasta la plataforma de distribución con múltiples columnas (cada análisis de distribución está en un hilo diferente), a la Generador de uniformes aleatorios Mersenne-Twister. Como puede ver, los subprocesos múltiples se realizan en muchos lugares diferentes.
Entonces, Realmente no tenemos una lista como esa. ¿Qué impulsa la pregunta aquí?
Hola jeff,
¿Dónde puedo encontrar qué plataformas/tareas integradas aprovechan el subproceso múltiple?
Como se señaló anteriormente, este deseo está más allá del alcance de lo que vamos a hacer en JSL. Si hay operaciones específicas que cree que se beneficiarían del subproceso múltiple, abra otros deseos con los detalles.
Si bien este deseo tiene muchos votos, desafortunadamente será difícil cumplir algo más que lo que ofrece Parallel Assign(). Debido a la estrecha integración con la interfaz de usuario y la naturaleza interactiva de JMP, no es posible proporcionar un entorno seguro para subprocesos sin limitar el JSL posible a esencialmente lo que permite Parallel Assign.
La mejor manera de aprovechar el subproceso múltiple es utilizar las plataformas integradas tanto como sea posible. Estas plataformas son donde podemos proporcionar soluciones multiproceso directamente.Abrir otros deseos para operaciones integradas en las que cree que el subproceso múltiple sería útil es la mejor manera de informarnos dónde le gustaría ver más subprocesos múltiples.
En cuanto a distribuir operaciones JSL simples en múltiples subprocesos, existe una función llamada Parallel Assign() para eso. Divide el trabajo en fragmentos donde el código de cada fragmento da como resultado un solo número y el resultado de toda la operación es una matriz de números.
Hay un ejemplo de juguete en el índice de secuencias de comandos para Parallel Assign(), y el segundo ejemplo para Frame Size() muestra un ejemplo más elaborado para calcular los datos del conjunto de Mandelbrot. Otro pequeño ejemplo está en @Craige_Hales 's Publicación del libro de cocina JSL sobre bucles y ahí está más sobre Mandelbot en su blog.
He incluido otro ejemplo a continuación que busca el archivo más grande en una lista de archivos que utilizan subprocesos múltiples. El script ejecuta primero una versión de un solo subproceso y puede ver ambos períodos de actividad en esta captura de pantalla del administrador de tareas. La versión de un solo hilo es la mesa larga y la versión paralela es la de pico alto. Para 17.000 archivos en 8 núcleos, el tiempo pasó de 13 segundos a 4,5 segundos, o 3 veces más rápido. No es lo ideal, pero como suele ser el caso, los subprocesos comparten algunos recursos, como el acceso al disco en este caso.
El JSL que se ejecuta en paralelo debe ser simple para que no modifique el estado global compartido. Es por eso que algunas variables globales se copian como primer paso. También significa que el código paralelo no puede hacer cosas como crear tablas de datos o interactuar con la pantalla.
Nos interesa saber en qué tipo de otras acciones simples podríamos necesitar una interfaz más rica. Una que yo sepa es que cada trabajador devuelva artículos distintos de los números. Básicamente, eso significaría usar una lista para los resultados en lugar de una matriz.
----
Names Default To Here( 1 );
// Example for Parallel Assign().
// get a list of a lot of files
dir = If(Host is("Mac"), "$SAMPLE_DATA", "$JMP_HOME");
all files = Files In Directory( dir, "recursive" );
naf = N Items( all files );
// convert relative paths to full paths
For( i = 1, i <= naf, i++,
all files[i] = dir || "/" || all files[i]
);
// Function that looks at a range of a given file list and returns
// the index of the largest file.
// Importantly, this function uses no global variables.
largest file = Function( {files, first, last},
{i, i large = -1, bytes large = -1, bytes},
For( i = first, i <= last, i++,
bytes = File Size( files[i] );
If( bytes > bytes large,
bytes large = bytes;
i large = i;
);
);
i large;
);
// Single-threaded approach: see all the files to the function.
t0 = Tick Seconds();
lf = largest file( all files, 1, naf );
t1 = Tick Seconds();
Show( naf, lf, all files[lf], t1 - t0 );
// about 13sec on my machine (17k files on Win)
wait(1); // so we can see a break in a CPU activity monitor
// Multi-threaded approach: break the list up into 8 ranges that
// can be handled by separate threads.
t0 = Tick Seconds();
num chunks = 8; // JMP may create this many threads, or fewer
// initialize to -1, so we can detect failure if desired
results = J( num chunks, 1, -1 );
Parallel Assign(
// copy these globals into the thread's local variables
{tf = Name Expr( largest file ), tfiles = all files, tn = num chunks},
// make this assignment for each chunk:
results[i] = Local( {n = N Items( tfiles )},
tf( tfiles, 1 + Floor( (i - 1) * n / tn ), Floor( i * n / tn ) )
)
);
// We need to call the function once more to see which of the top
// files is the overall largest.
top files = all files[results];
toplf = largest file( top files, 1, num chunks );
lf = results[toplf];
t1 = Tick Seconds();
Show( naf, lf, all files[lf], t1 - t0 );
// about 4.5sec