Parallel Assign() è lento su alcuni dispositiviCiao a tutti,
sembra esserci un problema con Parallel Assign() in combinazione con alcuni sistemi.
Ho accesso a 3 PC Windows 10 con JMP 16.1.:
- Laptop: Core i5-8350U (4 core) a 1,9 GHz, 16 GB di RAM
- Vecchia workstation: Xeon E5-1660 v4 (8 core) a 3,2 GHz, 256 GB di RAM
- Nuova workstation Xeon W-2145 (8 core) a 3,7 GHz, 128 GB di RAM
Ho confrontato le prestazioni della versione parallela e sequenziale del mio script di test utilizzando diverse dimensioni del problema su tutti i sistemi (scipt sotto).
Il risultato è stato sorprendentemente pessimo. Solo sul mio laptop la versione parallela è leggermente più veloce della versione sequenziale, ma fino a oltre 2 volte più lenta sulle workstation.
Qualcuno ha riscontrato problemi di prestazioni simili con Parallel Assign()? O lo sto usando male? Che cosa sta succedendo qui?
rapinare


n_different_ids = 100000;
<BR />// Just generate random data. Every 15 rows must be processed at the same time.
DT_Data = J( 15*n_different_ids, 9, 0 );
For ( i = 1, i <= n_different_ids, i++,
DT_Data[15*(i-1)+(1::15),0] = i + J( 15, 9, Random Normal() );
);
<BR />// some function
F_percentile = Function( {x , p},
x = Sort Ascending(x);
n = N Rows(x);
index = 1 + (n - 1) * p;
index_ibelow = Floor(index);
index_iabove = Ceiling(index);
h = index - index_ibelow;
result = (1 - h) * x[index_ibelow] + h * x[index_iabove];
result;
);
<BR />// parallel version
DT_Features = J( n_different_ids, 16, 0 );
start=tick seconds();
Parallel Assign( {
DT_Data = DT_Data,
F_percentile = Name Expr( F_percentile )
},
DT_Features[i,j] = (
i_same_group = Loc(DT_Data[15*(i-1)+(1::15), 1]);
data = DT_Data[15*(i-1)+i_same_group, 1+Ceiling(j/2)];
If (mod(j,2),
result = F_percentile(data, 0.95);
,
result = F_percentile(data, 0.05);
);
result;
)
);
time_parallel = tick seconds()-start;
Show(time_parallel);
Wait(0.1);
<BR />// sequential version
DT_Features = J( n_different_ids, 16, 0 );
start=tick seconds();
for(i=1,i<=n_different_ids,i++,
for(j=1,j<=16,j++,
i_same_group = Loc(DT_Data[15*(i-1)+(1::15), 1]);
data = DT_Data[15*(i-1)+i_same_group, 1+Ceiling(j/2)];
If (mod(j,2),
result = F_percentile(data, 0.95);
,
result = F_percentile(data, 0.05);
);
DT_Features[i,j] =result;
);
);
time_sequential = tick seconds()-start;
Show(time_sequential);
ScriptingRe: Parallel Assign() è lento su alcuni dispositiviQuesta è una macchina JMP16/win10 da 4 CPU 16 GB ~ 3 GHz sotto VirtualBox. Vedo la velocità che mi aspetterei (non 4X, ma comunque buona.)
n_different_ids = 100.000;
time_parallel = 13.98333333333333;
time_sequential = 37.7333333333333;
n_different_ids = 1.000.000;
time_parallel = 141.2333333333333;
time_sequential = 375.016666666667;
L'assegnazione parallela sta copiando una matrice grande per ciascuna CPU, ma i grafici lineari non suggeriscono che si tratti di un problema di paginazione, a queste dimensioni.
Guarda il monitor delle attività di Windows per l'utilizzo della CPU e della memoria (e del disco) e vedi se spiega qualcosa. Ho visto il 100% durante l'assegnazione parallela e il 25% durante il test sequenziale. Ho anche visto 7 GB utilizzati durante l'assegnazione parallela più grande.
responsabile delle attività
Re: Parallel Assign() è lento su alcuni dispositiviCiao Craige,
Sto solo guardando la mia workstation con le prestazioni peggiori ora (sotto). Non ho visto nulla di sospetto nel Task Manager. Ad eccezione della CPU, nulla è vicino alla piena occupazione.
Quello che ho notato anche è che JMP 15.2.1 è sempre più veloce nelle versioni parallela e sequenziale. Nel caso di n = 100.000 JMP 16.1 impiega circa 36s/18s (parallelo/sequenziale) e JMP 15.2.1 31s/15s, che è un po' meglio ma è ancora lontano da buone prestazioni in parallelo. Sfortunatamente, non ho più una versione precedente disponibile. Ho scritto questo codice usando JMP 12 e non ho notato problemi di prestazioni allora (e anche i PC che stavo usando erano diversi).
rapinare

Re: Parallel Assign() è lento su alcuni dispositiviPosso confermare questo comportamento sul mio laptop (Win 10, JMP 16.1):
time_parallel = 158.7;
time_sequential = 157.766666666667;
n=1000000
Re: Parallel Assign() è lento su alcuni dispositiviNon sono sicuro. Ho inviato una nota su questo thread a JMP; potresti voler parlare anche con il supporto tecnico.
La mia ipotesi (ed è tutto!) è che JMP dovrà cambiare qualcosa per ripristinare le prestazioni sul nuovo hardware. Con solo 4 CPU virtuali, non riesco a vedere la stessa cosa che vedi tu.
Re: Parallel Assign() è lento su alcuni dispositiviHo anche limitato il numero di core nel task manager disponibili per JMP a 2, 4 e 8 sulla nuova workstation. La versione parallela rimane ancora più lenta di quella sequenziale. La mia ipotesi è che JMP utilizzi librerie obsolete in background che funzionano male su nuove architetture hardware.
Grazie Craige, contatterò il supporto tecnico a riguardo.
Re: Parallel Assign() è lento su alcuni dispositiviPer la mia macchina a 4 core da 3,6 GHz e N=100k:
Sto ottenendo un'accelerazione di 1,4X utilizzando il codice parallelo su sequenziale (12,8 secondi paralleli vs 17,8 secondi sequenziali). Questo non è buono come l'accelerazione di 2,7X che Craige stava vedendo e ma è meglio del comportamento di rallentamento che vedevi sulle workstation. Tuttavia, volevo vedere se potevo ottenere un po' più di prestazioni da questo, quindi ho apportato alcune modifiche.
Ho rimosso l'overhead della chiamata di funzione (copie degli argomenti della matrice, ecc.) Usando invece le espressioni. Questo mi ha portato a un'accelerazione di 2,5 volte (4,5 secondi in parallelo contro 11,3 secondi in sequenza) e un po' più veloce dell'originale. E infine, ho provato a riorganizzare un po' i loop e ho ridotto la versione sequenziale a 4 secondi. Questo è più veloce della versione parallela, ma la riorganizzazione non è così facile da fare con Parallel Assign. Ho testato alcuni N diversi e questi pattern sembravano reggere, ma non ho eseguito uno sweep completo come nella tabella sopra. Trovi il codice allegato.
Parallelo: 12.78
Sequenziale: 17.80
Parallel_Expr: 4.50
Sequential_Expr: 11.27
Sequential_Expr_Opt: 3.98
Re: Parallel Assign() è lento su alcuni dispositiviOh, grazie! Eseguo il tuo script sulla mia nuova workstation che ottengo
Parallelo: 37.08333333333139
Sequenziale: 19.7166666666453
Parallel_Expr: 6.93333333331975
Sequential_Expr: 12.5333333333256
Sequential_Expr_Opt: 4.549999999998836
Non consideriamo quello Sequential_Expr_Opt perché è un confronto ingiusto. 
Hai appena sostituito la funzione con un'espressione e ottengo uno speedup di circa 1,5 per il sequenziale e più di 5 (!!!) per la versione parallela? È un'ottima soluzione. Quindi cosa imparo da questo? Non usi mai le funzioni in JSL? È un po' sgradevole perché le funzioni rendono il codice più leggibile e più facile e sicuro da usare e modificare per gli altri. Tuttavia, penso che ci sia ancora un problema dietro le quinte perché la mia versione parallela originale impiega ancora il doppio del tempo di quella sequenziale originale e questo non è il caso della macchina virtuale di Craige.
Aggiornamento: ecco la scansione completa sulla nuova workstation:


Re: Parallel Assign() è lento su alcuni dispositiviHo seguito i consigli di Craiges e ho contattato il supporto tecnico due settimane fa. Dopo alcune domande sui miei PC, ho ricevuto oggi la risposta che gli sviluppatori sono stati coinvolti per indagare sul comportamento e risolvere i problemi in una futura versione di JMP.
Tuttavia, grazie ancora Evan per aver velocizzato questo script specifico.
Re: Parallel Assign() è lento su alcuni dispositiviCiao @Robbb , due pensieri:
Programmazione per la velocità
L'obiettivo del tuo codice può avere un grande effetto sul modo in cui lo scrivi.Per la stragrande maggioranza degli script il tempo aggiuntivo necessario per chiamare una funzione o copiare un simbolo non ha importanza, quindi sì, dovresti usare le funzioni e rendere il codice facile da interpretare.D'altra parte, se stai lavorando a un progetto che sarà grande e verrà ripetuto abbastanza volte da preoccuparti di quanto tempo ci vorrà, allora sì, potresti voler iniziare a scambiare alcune sottigliezze per prestazioni grezze.Ti incoraggio a dedicare del tempo solo a ottimizzare le cose che contano davvero.Non passare un'ora in più a programmare qualcosa ora, e poi dedicare un'ora in più a capire cosa hai fatto dopo un anno perché l'hai reso più complesso cercando di velocizzarlo, solo per risparmiare agli utenti 20 secondi in più una volta al giorno .
Scambio parallelo
Quando si decide se eseguire in parallelo è necessario bilanciare l'overhead dell'impostazione di quel thread "figlio" con il lavoro che farà.Immagina di eseguire lavori paralleli aprendo un'altra copia di JMP, aprendo una tabella dati e facendo clic su Esegui. Se lo lasci in esecuzione per un'ora, è fantastico, risparmierai un sacco di tempo lasciando che uno script faccia tutto, ma se quello script verrà eseguito per 20 secondi, probabilmente hai speso più tempo per avviarlo, quindi hai salvato.Sì, l'overhead qui è molto più piccolo, ma copiare i simboli e allocare la memoria richiede tempo.Assicurati che il lavoro che farà il tuo script dopo la configurazione dell'ambiente sia sostanziale.Un modo per aiutare a far sì che ciò accada è spezzare il ciclo in sole 4 parti e fare in modo che ogni thread lavori su un quarto dei valori contemporaneamente.Quindi, dividi il tuo elenco in quattro parti, ciascuna con un quarto delle righe, quindi fai in modo che il tuo script elabori in sequenza ogni sottoelenco. In questo modo riduci il tempo impiegato nell'impostazione di thread figlio da n volte () a 4.
Re: Parallel Assign() è lento su alcuni dispositiviCiao @ih ,
essere d'accordo.
Il sovraccarico di creare un bambino non ha molta importanza nel mio caso, quindi non ho dedicato molto tempo a renderlo il più efficace possibile. Questo script non è pensato per essere eseguito solo per pochi minuti. Prima di aprire questo topic ho fatto esattamente quello che mi hai suggerito. Ho suddiviso il mio set di dati in 8 parti ed è stato completato entro 0,5 giorni. Per interesse ho provato anche la versione "Sequential_Expr_Opt" di Evan in seguito, e ci sono voluti tra 1,5 e 4 giorni per finire sul mio set di dati (iniziato giovedì mattina, non finito venerdì pomeriggio ma lunedì mattina).
Questo thread era per mostrare che c'è qualcosa di sbagliato dietro le quinte in generale. In passato ho notato di tanto in tanto cattive prestazioni parallele di JMP e mi dava fastidio. Mi piace JMP e mi piace provare cose con esso ciò che gli altri dicono che non può essere fatto con JMP. E sono più che felice che gli sviluppatori lo stiano esaminando.
Tuttavia, devo dire che ci sono strumenti migliori per gestire set di dati davvero grandi rispetto a JMP. Almeno al momento. 