Beim Schreiben des folgenden Matlab-Codes:
%Vor%Ich erhalte die folgende Warnung m-lint :
Die Variable
x
scheint die Größe bei jeder Schleifeniteration zu ändern
Meine Frage:
Diese Frage ist kein Duplikat von diesem , da es sich um allgemeinere Aspekte der Vorallokation handelt, eher eine spezifische Instanz davon .
Nun, zuerst zuerst.
Dieser Code ist syntaktisch korrekt und wird korrekt ausgeführt, wobei das erwartete Ergebnis zurückgegeben wird: Das ii
-te Element von x
enthält den Wert foo( ii )
.
Bevor jedoch dieser kleine Codeabschnitt ausgeführt wird, ist die Variable x
nicht definiert. Jetzt, wenn die Schleife beginnt, wird x(1)
der Wert foo( 1 )
zugewiesen, und so erstellt Matlab x
als Länge-1-Array. Bei der zweiten Iteration wird x(2)
den Wert foo( 2 )
zugewiesen und daher muss Matlab x
auf Länge 2 ändern usw. x
ändert seine Länge / Größe bei jeder Iteration.
Überlegen Sie, was im Hintergrund geschieht (hinsichtlich der Speicherzuweisung), wenn x
bei jeder Iteration seine Größe ändert: Bei jeder Iteration muss Matlab einen freien Speicherplatz finden, um die neue Größe von x
zu hosten. Wenn du Glück hast, gibt es genug freien Speicherplatz direkt nach x
, also passiert nur eine Änderung der Menge an Speicher, die x
zugewiesen wurde und schreibe den neuen Wert an der richtigen Stelle.
Wenn jedoch nicht genügend freier Speicherplatz unmittelbar nach x
vorhanden ist, muss Matlab einen neuen Platz für all die ii-1
-Elemente bereits in x
finden, diesen neuen Platz für x
zuweisen , kopiere alle ii-1
-Werte bereits in x
auf den neuen Ort und gib den alten Ort x
frei. Diese im Hintergrund stattfindenden Operationen ohne Zuteilung und Kopieren können extrem zeitaufwendig sein, insbesondere wenn x
groß ist.
Die einfachste Lösung besteht darin, den gesamten Speicherplatz x
vor der Schleife
Durch die Vorbelegung stellen wir sicher, dass x
den gesamten Speicher, den sie benötigt, im Voraus zugewiesen hat. Daher ist keine kostspielige Speicherzuweisung / -kopie erforderlich, wenn die Schleife ausgeführt wird.
Wenn Sie zu faul sind (wie ich) und nicht vorbelegen wollen, können Sie einfach:
%Vor% Auf diese Weise erhält das erste Mal x
einen Wert, der seinem n
-ten Element zugewiesen wird (das letzte) und daher weist Matlab sofort Raum für alle n
zu. Elemente von x
.
Cool!
Meine Antwort ist ein bisschen spät, aber es gibt ein paar Dinge, die ich in Bezug auf Array-Wachstum und Vor-Zuweisung in MATLAB erwähnen würde.
Das erste, was zu beachten ist, ist, dass MATLAB die automatische Array-Wachstumsleistung in den letzten Versionen stark verbessert hat, so dass der durch die Warnung implizierten Performance-Hit nicht zu schlecht ist wenn Sie es richtig machen (siehe unten). Dennoch empfiehlt es sich, Ihr Array vorab zuzuweisen (z. B. mit zeros
).
Ab R2014a wird in der ausführlichen Erläuterung der Warnung Folgendes angegeben:
Die Größe der angegebenen Variablen oder des Arrays scheint sich mit jeder Schleifeniteration zu ändern. In der Regel wird diese Nachricht angezeigt, weil ein Array durch Zuweisung oder Verkettung wächst. Das Wachsen eines Arrays durch Zuweisung oder Verkettung kann teuer sein. Bei großen Arrays muss MATLAB einen neuen Speicherblock zuweisen und den älteren Array-Inhalt in das neue Array kopieren, wenn er die Zuweisung vornimmt.
Programme, die auf diese Weise die Größe einer Variablen ändern, können den größten Teil ihrer Laufzeit in dieser ineffizienten Aktivität verbringen. ...
Aus diesem Auszug sollte ziemlich klar sein, warum die Vorabzuweisung eine kluge Idee ist, wenn Sie sich überhaupt mit der Leistung befassen.
Randbemerkung: Es gibt nur wenige Informationen über den Algorithmus, der für die Neuzuweisung während des Array-Wachstums verwendet wird. Einige Informationen wurden jedoch von Steve Eddins in demselben Blogpost bereitgestellt, den ich in diese vorherige Antwort .
Wenn Sie die dynamische Größenanpassung von Arrays verwenden möchten, indem Sie entlang einer Dimension wachsen (ohne Vorbelegung), gibt es Möglichkeiten, dies richtig zu machen. Sehen Sie sich dies an MathWorks Blog-Post von Steve Eddins . Das Wichtigste, was Sie beachten sollten, ist, dass Sie für die beste Leistung entlang der letzten Dimension wachsen sollten. Dies ist in Ihrem Fall kein Problem, da das Array 1D ist. Also, wenn Sie sich entscheiden, es fahren zu lassen, setzen Sie %#ok<SAGROW>
auf die gleiche Zeile wie die Warnung nach dem Täter-Code, um die Warnung zum Schweigen zu bringen.
Yair erläutert die dynamische Größenanpassung von Arrays in einem anderen Beitrag in seinem Blog . Es gibt auch Möglichkeiten, ein Array zuzuordnen, ohne mit einigen haarigen MEX-API-Akrobaten zu initialisieren, aber das ist es.
Die Vorabzuweisung wird empfohlen. Gewöhne dich an, lerne zeros
zu lieben. Wenn Sie fest entschlossen sind, MATLAB jedes bisschen Leistung abzunehmen, hat Yair Altman ein paar exzellente Artikel zum Thema Speichervorbelegung:
Es gibt eine Menge Material zu dem Thema. Hier sind ein paar ausgewählte Links für weitere Informationen:
Offizielle Dokumentation und technische Lösungen:
MathWorks-Blogs:
Community Blogs:
Verwandte Stapelüberlauffragen / Antworten:
Diese Antwort ist vereinfacht, einige der Details verschont.
M-Lint warnt den Programmierer, wenn er eine Gelegenheit zur Vorbelegung von Speicher entdeckt. Die Vorbelegung von Speicher verbessert die Verarbeitungszeit, da Aufgaben außerhalb der direkten Steuerung eines MATLAB-Programmierers in Bezug auf die Speicher-Hardware-Verwaltung vereinfacht werden.
Eine sich ändernde Variablengröße ist nicht immer schlecht; Es ist jedoch eine gute Programmierpraxis, für eine schnellere Verarbeitungsgeschwindigkeit zu kodieren. Eine schnellere Verarbeitungsgeschwindigkeit macht sich mehr bemerkbar, wenn der Code viele Iterationen oder viel mehr Speicher verwendet.
Andere empfohlene MATLAB-Vorbelegungsmethoden werden funktionieren; Die folgenden Methoden sind jedoch möglicherweise intuitiver.
Zuweisen eines Werts zu einem zuvor zugewiesenen Array.
%Vor%Anmerkungen:
Einem vorbelegten mehrdimensionalen Array einen Wert zuweisen:
%Vor%Eine einfache Art der Vorbelegung besteht darin, nur dem letzten Element in einem Array eine Null zuzuweisen.
%Vor%Tags und Links matlab memory-management iteration