Stavo leggendo a useful post at WRI blog on improving speed of code, e ho bisogno di aiuto per capire questo.differenza di velocità nel fare una tabella
confrontare questi costi
Timing[
tbl = Table[i + j, {i, 1, 1000}, {j, 1, 1000}];
]
{0.031, Null}
e
Timing[
a = 1000;
tbl = Table[i + j, {i, 1, a}, {j, 1, a}];
]
{0.422, Null}
Quindi è molto più veloce quando mettere il valore effettivo per il limite all'interno della tabella stessa vs esterno. La spiegazione per questo, che sono sicuro sia corretta, ma ho bisogno di aiuto nella comprensione, è che Table
è compilato se il suo limite è numerico o no, questo perché i suoi Attributi sono HoldAll
.
Ma la mia domanda è: come funzionerebbe il precedente, perché i limiti a Table
devono, a un certo punto, diventare comunque numerici? Non riesco a scrivere
Clear[a]
tbl = Table[i + j, {i, 1, a}, {j, 1, a}]
Quanto sopra dà un errore.
Quindi, per me, la scrittura a=1000
fuori Table
vs interno, dovrebbe aver fatto alcuna differenza, poiché senza a
avere un valore numerico, Table[]
non possono fare nulla. Quindi la sostituzione di a
con il numero 1000 deve avvenire in un punto dal valutatore prima che lo Table[]
possa fare qualcosa di utile, non sarebbe?
In altre parole, quello che Table
dovrebbe vedere, alla fine, è {i, 1, 1000}, {j, 1, 1000}
in entrambi i casi.
Quindi, il modo in cui ho pensato che questo sarebbe accaduto è questo:
- Evaluator sostituisce
a
per 1000 negli argomenti della tavola - Evaluator chiama
Table
con il risultato, che è ora tutto numerica. - Tabella Compila e ora è più veloce.
Ma quello che sembra succedere è qualcos'altro. (a causa di HoldAll
?)
- La tabella prende i suoi argomenti, così com'è. Poiché ha HoldAll, quindi vede
a
e non 1000. - Non chiama Compile poiché i suoi argomenti non sono tutti i numeri.
- Ora generare una tabella con il limite
a
, valutatore restituiscea
a 1000 - Tabella viene generato adesso tutti i limiti sono numerici, ma più lento ora poiché il codice non viene compilato.
La domanda è: cosa succede sopra? Qualcuno potrebbe spiegare i passi che sarebbero accaduti per spiegare questa differenza nei tempi?
Inoltre, come si potrebbe assicurare che la tabella è stata compilata in entrambi i casi nell'esempio precedente, anche se si utilizza una variabile per il limite?Non è sempre possibile codificare i numeri per i limiti del tavolo, ma a volte si deve usare una variabile per questi. Si dovrebbe usare esplicitamente il comando Compile
? (Non uso direttamente lo Compile
, poiché presumo che venga eseguito automaticamente quando necessario).
di modifica (1)
In risposta al post di Mike in basso a trovare alcuna differenza nei tempi quando si utilizza una chiamata.
ClearAll[tblFunc];
Timing[a = 1000;
tblFunc[a_] := Table[i + j, {i, 1, a}, {j, 1, a}];
Developer`PackedArrayQ[tblFunc[a]]
]
dà
{0.031, True}
Ma questo è perché a
è ora il numero 1000
all'interno della funzione, una volta che è chiamato. Poiché M passa le cose per VALUE.
Se si forza la chiamata ad essere per riferimento, in modo che a
è lasciato non valutata, allora otteniamo
ClearAll[tblFunc];
Timing[a = 1000;
tblFunc[a_] := Table[i + j, {i, 1, a}, {j, 1, a}];
Developer`PackedArrayQ[tblFunc[[email protected]]]
]
ora vediamo il risultato atteso, dal momento che ora a
è ancora simbolica all'interno della funzione, siamo torna al punto di partenza, e ora è lento, dal momento che non è imballato. E poiché non è impacchettato, Compile non viene utilizzato.
{0.437, False}
modifica (2) Grazie a tutti per le risposte, penso che ho imparato da loro assegnare.
Ecco un riepilogo esecutivo, solo per essere sicuro di avere tutto ok.
modifica (3)
Ecco i link che ho particolarmente legati alla suggerimenti da utilizzare per rendere il codice di Mathematica corre più veloce.
- http://library.wolfram.com/howtos/faster/
- http://blog.wolfram.com/2011/12/07/10-tips-for-writing-fast-mathematica-code/
- https://stackoverflow.com/questions/4721171/performance-tuning-in-mathematica
- Using Array and Table Functions in Mathematica. Which is best when
Nota che puoi avere cose come 'Tabella [i + j, {i, 1, 1000}, {j, 1, i}]' che è un motivo per 'Tabella' da non precompilare quando i limiti non sono tutti i numeri. –
Domanda correlata: http://stackoverflow.com/questions/5764774/using-array-and-table-functions-in-mathematica-which-is-best-when/ –
@David Sono d'accordo con la tua affermazione, voglio solo sottolinea che la vera ragione per cui 'Table' è lenta per gli iteratori simbolici sembra essere che non può determinare se il risultato sarà o meno un array * rettangolare * e, quindi, non può usare matrici compresse. Il fatto che non possa quindi usare 'Compile' ne deriva - perché gli array compressi sono ciò che dà a' Compile 'i suoi guadagni in termini di efficienza (almeno quando si compila su MVM target, che è quello che credo stia accadendo in auto-compilation). –