Variable scheint die Größe bei jeder Schleifeniteration zu ändern - was?

8

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:

  1. Was bedeutet diese Warnung?
  2. Warum ist die Änderung der Variablengröße bei jeder Iteration eine schlechte Sache?
  3. Wie kann dieses Problem gelöst werden?

Diese Frage ist kein Duplikat von diesem , da es sich um allgemeinere Aspekte der Vorallokation handelt, eher eine spezifische Instanz davon .

    
Shai 09.01.2014, 14:38
quelle

4 Antworten

16

Nun, zuerst zuerst.

1. Was bedeutet diese Warnung?

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.

2. Warum ist die Änderung der Variablengröße bei jeder Iteration eine schlechte Sache?

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

3. Wie kann dieses Problem gelöst werden?

Die einfachste Lösung besteht darin, den gesamten Speicherplatz x vor der Schleife

zu reservieren %Vor%

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.

Eine alternative coole Lösung für das Problem

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!

    
Shai 09.01.2014, 14:38
quelle
11

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

Die Warnung erklärt

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 .

Automatische Optimierung des Array-Wachstums

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.

Vorbelegung

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:

chappjc 23.01.2014 22:50
quelle
1

Diese Antwort ist vereinfacht, einige der Details verschont.

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

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

  3. Andere empfohlene MATLAB-Vorbelegungsmethoden werden funktionieren; Die folgenden Methoden sind jedoch möglicherweise intuitiver.

    • Zuweisen eines Werts zu einem zuvor zugewiesenen Array.

      %Vor%

      Anmerkungen:

      • Die Zuweisung von NaN während der Vorbelegung kann vorteilhaft sein, da ein NaN im Array gefunden wird, bedeutet, dass der Wert nicht zugewiesen wurde.
      • Bei der Vorbelegung in einer Dimension werden Einsen (n), Nullen (n) oder NaN (n) eine n x n-Matrix zuweisen. Wenn Sie mit einem extrem großen Datensatz arbeiten, kann dies die Berechnungsgeschwindigkeit verlangsamen.
    • 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%
Agriculturist 16.10.2015 19:14
quelle