2013-08-10 2 views
9

Die Matlab documentation sagt, dassMehr zur Verwendung von i und j als Variablen in Matlab: Geschwindigkeit

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

a = i; 

use

a = 1i; 

Der Robustheit Teil klar ist, as there might be variables called i or j. Wie jedoch für Geschwindigkeit, ich habe einen einfachen Test in Matlab 2010b gemacht und ich erhalten Ergebnisse, die den Anspruch zu widersprechen scheinen:

>>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. 

Irgendwelche Ideen? Könnte es ein versionsbezogenes Problem sein?

Nach Erläuterungen von @TryHard und @horchler, ich habe auf die Variable a andere Werte versucht, die Zuordnung, mit diesen Ergebnissen:

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

Wie wäre es mit dem allgemeineren Fall von '2 * i' vs.' 2i' (oder sogar '2 * 1i')? – horchler

+0

Ich sehe eine x 5 Verbesserung mit R14 auf Rinky Dink Laptop mit XP. –

+0

Ich würde 'clear all 'vor jeder Schleife anwenden? –

Antwort

9

Ich glaube, Sie bei einem pathologischen Beispiel suchen. Versuchen Sie, etwas komplexere (Ergebnisse für R2012b auf OSX angezeigt):

(wiederholte Addition)

>> 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 

(wiederholte Multiplikation)

>> 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

"Versuchen Sie etwas komplexer ..." -pun beabsichtigte ich hoffe. :-) – horchler

+0

Es kann sein, wie du sagst. Dann, der Anspruch "Für Geschwindigkeit und verbesserte Robustheit, können Sie komplexe i und j durch 1i ersetzen. Zum Beispiel statt a = i; verwenden Sie a = 1i" in der Dokumentation ist streng falsch –

+1

Für die Robustheit ist die Dokumentation korrekt (Wenn Sie beispielsweise versehentlich "i = 3" ausführen, wird "a = i" 3, aber "a = 1i" wird standardmäßig zu komplex "i"), aber ich stimme zu, dass nicht klar ist, warum sie Geschwindigkeitsüberlegungen hinzugefügt haben – SheetJS

5

Eine Sache zu erinnern ist, dass Optimierungen anders angewendet werden, ob Sie laufen von der Kommandozeile oder einer gespeicherten M-Funktion. Hier

ist ein Test meiner eigenen:

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 

Die Ergebnisse auf meinem Windows-Rechner läuft 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) 

Beachten Sie, dass die Ergebnisse ein wenig mit verschiedenen Läufen schwanken, wo die Reihenfolge der Anrufe werden gemischt. Also nimm die Zeiten mit einem Körnchen Salz.

Meine Schlussfolgerung: spielt keine Rolle in Bezug auf Geschwindigkeit, wenn Sie 1i oder 1*i verwenden.


Ein interessanter Unterschied ist, dass, wenn Sie auch eine Variable im Funktionsumfang haben, wo Sie es auch als imaginäre Einheit verwenden, MATLAB einen Fehler wirft:

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. 

die Fehler zu sehen, ändern die obige Funktion in test3:

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

dh wurde die variable i sowohl als eine Funktion und eine Variable in dem gleichen lokalen Bereich verwendet.

+2

Ich wette, wenn Sie diese Funktionen vor dem Timing "aufwärmen", werden alle Unterschiede im Rauschen verschwinden. – horchler

+0

Für mich mit oder ohne Aufwärmen waren die Ergebnisse gleich: etwa 0,43 für die ersten vier Methoden (kein signifikanter Unterschied), dann 0,58 bzw. 1,2. Ran es mehrmals und die letzten beiden sind deutlich langsamer als die ersten vier. –

+2

wahr, die Art, wie ich das Timing gemessen habe, ist nicht sehr genau. Eine bessere Lösung ist die Verwendung von [TEITEIT] (http://www.mathworks.com/matlabcentral/fileexchange/18798-timeit-benchmarking-function) aus dem Dateiaustausch, der dafür sorgt, dass der Code mehrere Male ausgeführt wird Die Ergebnisse werden gemittelt, wobei der Overhead für das Aufrufen von Funktionen berücksichtigt wird ... Sie werden sich freuen, dass die nächste Version von MATLAB (Vorabversion, wie Sie wissen) diese Funktion nativ enthält! – Amro

Verwandte Themen