Con l'avanzare dell'informatica, sono passato da 1 core a 2 core a 4 core... a 64 thread sulla mia workstation. Nel frattempo .jsl è rimasto effettivamente a thread singolo. So che alcune piattaforme utilizzeranno tutti i thread, ma mi piacerebbe essere in grado di eseguire semplici operazioni jsl a piacimento su più thread. Ad esempio, se ho uno script che opera per riga su 10.000.000 di righe di dati, se sto eseguendo l'iterazione per riga in un ciclo for e so che il risultato di ciascuna riga è indipendente dalle altre righe, vorrei dividerlo operazione in 64 cicli for asincroni, sospendere altre esecuzioni mentre i 64 cicli vengono completati in parallelo, quindi tornare a uno script sincrono a thread singolo dopo che tutti sono stati completati, proprio come farei in .py con Pool() e poolObject.join.
Ciao Steve,
Ci sono molti posti in JMP in cui cerchiamo di sfruttare più core: tutto, dal salvataggio/apertura di una tabella di dati compressa (ogni colonna viene inviata a un thread diverso), alla piattaforma di distribuzione con più colonne (ogni analisi di distribuzione è un thread diverso), al Generatore di uniformi casuali Mersenne-Twister. Come puoi vedere il multi-threading viene eseguito in molti posti diversi.
COSÌ, non abbiamo davvero un elenco del genere. Cosa spinge la domanda qui?
Ciao Jeff,
Dove posso trovare quali piattaforme/attività integrate sfruttano il multi-threading?
Come notato direttamente sopra, questo desiderio va oltre lo scopo di ciò che faremo in JSL. Se ci sono operazioni specifiche che ritieni possano trarre vantaggio dal multithreading, apri altri desideri con i dettagli.
Sebbene questo desiderio abbia molti voti, sfortunatamente qualcosa di più di quanto offerto da Parallel Assign() sarà difficile da soddisfare. A causa della stretta integrazione con l'interfaccia utente e della natura interattiva di JMP, non è possibile fornire un ambiente thread-safe senza limitare il possibile JSL essenzialmente a ciò che consente Parallel Assign.
Il modo migliore per sfruttare il multithreading è utilizzare il più possibile le piattaforme integrate. Queste piattaforme sono dove possiamo fornire direttamente soluzioni multithread.Aprire altri desideri per le operazioni integrate in cui ritieni che il multithreading sarebbe utile è il modo migliore per farci sapere dove ti piacerebbe vedere più multithreading.
Per quanto riguarda l'esecuzione di semplici operazioni JSL su più thread, esiste una funzione chiamata Parallel Assign() per questo. Suddivide il lavoro in blocchi in cui il codice per ciascun blocco risulta in un singolo numero e il risultato dell'intera operazione è una matrice di numeri.
C'è un esempio giocattolo nell'indice di scripting per Parallel Assign(), e il secondo esempio per Frame Size() mostra un esempio più elaborato per il calcolo dei dati dell'insieme di Mandelbrot. Un altro piccolo esempio è qui @Craige_Hales 'S Post del libro di ricette JSL sui loop e c'è di più su Mandelbot nel suo blog.
Di seguito ho incluso un altro esempio che trova il file più grande in un elenco di file che utilizzano il multi-threading. Lo script esegue prima una versione a thread singolo e puoi vedere entrambi gli scatti di attività in questo screenshot del task manager. La versione a filo singolo è la mesa lunga e la versione parallela è il picco alto. Per 17.000 file su 8 core, il tempo è passato da 13 secondi a 4,5 secondi, ovvero 3 volte più veloce. Non è l'ideale, ma come spesso accade, i thread condividono alcune risorse, come in questo caso l'accesso al disco.
Il JSL eseguito in parallelo deve essere semplice in modo da non modificare lo stato globale condiviso. Ecco perché alcuni valori globali vengono copiati come primo passaggio. Significa anche che il codice parallelo non può fare cose come creare tabelle di dati o interagire con il display.
Siamo interessati a sapere che tipo di altre azioni semplici per le quali potremmo aver bisogno di un'interfaccia più ricca. Uno che conosco è che ciascun lavoratore restituisca articoli diversi da quelli numerici. In sostanza, ciò significherebbe utilizzare un elenco per i risultati anziché una matrice.
----
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