2013-08-10 12 views
9

Il Matlab documentation dice chePiù sull'uso i e j come variabili in Matlab: velocità

For speed and improved robustness, you can replace complex i and j by 1i. For example, instead of using

a = i; 

use

a = 1i; 

Il robustezza parte è chiaro, as there might be variables called i or j. Tuttavia, per quanto riguarda la velocità , ho fatto un semplice test in Matlab 2010b e ottenere risultati che sembrano contraddire l'affermazione:

>>clear all 

>> a=0; tic, for n=1:1e8, a=i; end, toc 
Elapsed time is 3.056741 seconds. 

>> a=0; tic, for n=1:1e8, a=1i; end, toc 
Elapsed time is 3.205472 seconds. 

Tutte le idee? Potrebbe essere un problema relativo alla versione?

Dopo i commenti di @TryHard e @horchler, ho provato l'assegnazione di altri valori alla variabile a, con questi risultati:

Increasing order of elapsed time:

"i" < "1i" < "1*i" (trend "A")

"2i" < "2*1i" < "2*i" (trend "B")

"1+1i" < "1+i" < "1+1*i" (trend "A")

"2+2i" < "2+2*1i" < "2+2*i" (trend "B")

+0

E il caso più generale di '2 * i' contro' 2i' (o anche '2 * 1i')? – horchler

+0

Vedo un miglioramento x 5 con R14 sul portatile rinky dink con XP. –

+0

Applicheremo 'clear all' prima di ogni ciclo? –

risposta

9

penso che si sta guardando un esempio patologico. Provare qualcosa di più complesso (risultati mostrata per R2012b su OSX):

(ripetuto oltre)

>> clear all 
>> a=0; tic, for n=1:1e8, a = a + i; end, toc 
Elapsed time is 2.217482 seconds. % <-- slower 
>> clear all 
>> a=0; tic, for n=1:1e8, a = a + 1i; end, toc 
Elapsed time is 1.962985 seconds. % <-- faster 

(ripetuto moltiplicazione)

>> clear all 
>> a=0; tic, for n=1:1e8, a = a * i; end, toc 
Elapsed time is 2.239134 seconds. % <-- slower 
>> clear all 
>> a=0; tic, for n=1:1e8, a = a * 1i; end, toc 
Elapsed time is 1.998718 seconds. % <-- faster 
+13

"Prova qualcosa di più complesso ..." -pun intenzione che spero. :-) – horchler

+0

Potrebbe essere come dici tu. Quindi, l'affermazione "Per velocità e robustezza migliorata, è possibile sostituire i complessi i e j di 1i. Ad esempio, invece di usare a = i; utilizzare a = 1i" nella documentazione è assolutamente errato –

+1

Per motivi di robustezza, la documentazione è corretta (per esempio, se si esegue inavvertitamente 'i = 3', quindi' a = i' imposterà 3 ma 'a = 1i' imposterà il complesso' i'), ma sono d'accordo che non è chiaro il motivo per cui hanno aggiunto considerazioni sulla velocità – SheetJS

5

Una cosa da ricordare è che le ottimizzazioni siano applicate in modo diverso se stai correndo dalla riga di comando o una funzione M salvata.

Ecco una prova della mia:

function testComplex() 
    tic, test1(); toc 
    tic, test2(); toc 
    tic, test3(); toc 
    tic, test4(); toc 
    tic, test5(); toc 
    tic, test6(); toc 
end 

function a = test1 
    a = zeros(1e7,1); 
    for n=1:1e7 
     a(n) = 2 + 2i; 
    end 
end 

function a = test2 
    a = zeros(1e7,1); 
    for n=1:1e7 
     a(n) = 2 + 2j; 
    end 
end 
function a = test3 
    a = zeros(1e7,1); 
    for n=1:1e7 
     a(n) = 2 + 2*i; 
    end 
end 

function a = test4 
    a = zeros(1e7,1); 
    for n=1:1e7 
     a(n) = 2 + 2*j; 
    end 
end 

function a = test5 
    a = zeros(1e7,1); 
    for n=1:1e7 
     a(n) = complex(2,2); 
    end 
end 

function a = test6 
    a = zeros(1e7,1); 
    for n=1:1e7 
     a(n) = 2 + 2*sqrt(-1); 
    end 
end 

I risultati sulla mia macchina Windows che eseguono R2013a:

>> testComplex 
Elapsed time is 0.946414 seconds. %// 2 + 2i 
Elapsed time is 0.947957 seconds. %// 2 + 2j 
Elapsed time is 0.811044 seconds. %// 2 + 2*i 
Elapsed time is 0.685793 seconds. %// 2 + 2*j 
Elapsed time is 0.767683 seconds. %// complex(2,2) 
Elapsed time is 8.193529 seconds. %// 2 + 2*sqrt(-1) 

Nota che i risultati oscillano un po 'con diverse corse in cui l'ordine di le chiamate vengono mescolate. Quindi prendi i tempi con un pizzico di sale.

La mia conclusione: non importa in termini di velocità se si utilizza 1i o 1*i.


Una differenza interessante è che se si dispone anche di una variabile nel campo di applicazione funzione in cui si usa anche come l'unità immaginaria, MATLAB getta un errore:

Error: File: testComplex.m Line: 38 Column: 5 
"i" previously appeared to be used as a function or command, conflicting with its 
use here as the name of a variable. 
A possible cause of this error is that you forgot to initialize the variable, or you 
have initialized it implicitly using load or eval. 

Per vedere l'errore, il cambiamento quanto sopra test3 funzione in:

function a = test3 
    a = zeros(1e7,1); 
    for n=1:1e7 
     a(n) = 2 + 2*i; 
    end 
    i = rand();  %// added this line! 
end 

per esempio, la variabile i stato utilizzato sia come una funzione e una variabile nello stesso ambito locale.

+2

Scommetto che se "riscaldi" quelle funzioni prima di cronometrarle, eventuali differenze spariranno nel rumore. – horchler

+0

Per me con o senza riscaldamento i risultati sono stati gli stessi: circa 0,43 per i primi quattro metodi (nessuna differenza significativa) quindi 0,58 e 1,2 rispettivamente. L'ho provato più volte e gli ultimi due sono molto più lenti dei primi quattro. –

+2

vero, il modo in cui ho misurato i tempi non è molto accurato. Una soluzione migliore è utilizzare [TIMEIT] (http://www.mathworks.com/matlabcentral/fileexchange/18798-timeit-benchmarking-function) da File Exchange, che si occupa di riscaldare il codice, eseguendolo più volte e calcolando la media dei risultati, tenendo conto del sovraccarico delle funzioni di chiamata ... Sarai felice di sapere che la prossima versione di MATLAB (prerelease di know-how) include questa funzione in modo nativo! – Amro

Problemi correlati