Durch Zuweisen einer Matrix zu einem viel größeren zugewiesenen Speicher dupliziert matlab sie irgendwie, während sie "kopiert" wird. Wenn die zu kopierende Matrix groß genug ist, kommt es zu einem Speicherüberlauf. Dies ist der Beispielcode:
main_mat=zeros(500,500,2000);
n=500;
slice_matrix=zeros(500,500,n);
for k=1:4
parfor i=1:n
slice_matrix(:,:,i)=gather(gpuArray(rand(500,500)));
end
main_mat(:,:,1+(k-1)*n:1+(k-1)*n+n-1)=slice_matrix; %This is where the memory will likely overflow
end
Jeder Weg, um nur die zu "zerschlagen" slice_matrix
das main_mat
ohne Overhead auf das zu ? Danke im Voraus.
BEARBEITEN:
Der Überlauf trat auf, wenn er main_mat
vorher zugewiesen wurde. Wenn main_mat
mit main_mat=zeros(500,500,1);
(kleinere Größe) initialisiert wird , tritt der Überlauf nicht auf, er verlangsamt sich jedoch, da die Zuordnung nicht erfolgt, bevor die Matrix zugewiesen wird. Dies verringert die Leistung erheblich, wenn der Bereich k
zunimmt.
matlab
optimization
Gregor Isack
quelle
quelle
parfor
Optimierungszwecken auf eine Schleife zu setzen . Kopiertparfor
Ihre Daten außerdem auf jeden einzelnen Worker. Unter der Annahme, dass 4 Worker Ihre Daten viermal im RAM duplizieren.memory
Funktion? Der Task-Manager? Ein Speicherfehler von Matlab? In welcher Codezeile passiert es?main_mat(:,:,1+(k-1)*n:1+(k-1)*n+n-1)
das Problem des Speicherüberlaufs auf. Es wird überprüft, wenn ich dasmain_mat
zuvor zugewiesen habe . Es läuft über, wenn ich es nicht tue, wird es nicht überlaufen. Matlab gibt den Fehler "Nicht genügend Speicher" zurück.h=h+slice_matrix(end)
Vorher einfügenmain_mat(:,:,1+(k-1)*n:1+(k-1)*n+n-1)=slice_matrix;
(und h mit 0 initialisieren)? Ich vermute, dass diese neu hinzugefügte Zeile bereits Speicherprobleme verursacht.Antworten:
Das Hauptproblem ist, dass Zahlen mehr Platz als Nullen benötigen.
main_mat=zeros(500,500,2000);
benötigt wenig RAM, währendmain_mat = rand(500,500,2000);
viel benötigt wird, egal ob Sie GPU oder parfor verwenden (in der Tat werden Sie durch parfor mehr RAM verwenden). Dies ist also keine unnatürliche Schwellung des Gedächtnisses. Nach Daniels Link unten scheint die Zuweisung von Nullen nur Zeiger auf den Speicher zu erzeugen, und der physische Speicher wird nur gefüllt, wenn Sie die Matrix für "Zahlen" verwenden. Dies wird vom Betriebssystem verwaltet. Und es wird für Windows, Mac und Linux erwartet, entweder Sie tun es mit Matlab oder anderen Sprachen wie C.quelle
zeros
gesamten virtuellen Speicher eingebe, wird dieser tatsächlich zugewiesen, aber es wird kein Speicher verwendet.whos
zeigt für beide Matrizen die gleiche Größe, während mein Betriebssystem einen unterschiedlichen Speicherverbrauch zeigt. Ich habe meinen Kommentar gelöscht, weil Ihre Antwort definitiv nicht falsch ist.ones
stattdessen mitzeros
, dies stellt sicher, dass der Speicher zum Zeitpunkt des Aufrufs der jeweiligen Funktion tatsächlich zugewiesen ist.main_mat
Werte ungleich Null zugewiesen werden. Bisher wurde nur virtueller Speicher (Adressraum) zugewiesen, dieser wird jetzt dem physischen Speicher zugewiesen.Das Entfernen
parfor
wird wahrscheinlich Ihr Problem beheben.parfor
ist dort nicht nützlich. MATLABsparfor
keine Parallelität des gemeinsam genutzten Speichers (dh es werden keine neuen Threads gestartet), sondern eine Parallelität des verteilten Speichers (es werden neue Prozesse gestartet). Es ist so konzipiert, dass die Arbeit auf einen Satz oder Arbeitsknoten verteilt wird. Obwohl es auch innerhalb eines Knotens (oder eines einzelnen Desktop-Computers) funktioniert, um die Arbeit auf mehrere Kerne zu verteilen, ist es keine optimale Methode, um Parallelität innerhalb eines Knotens durchzuführen.Dies bedeutet, dass jeder der von gestarteten Prozesse
parfor
eine eigene Kopie haben mussslice_matrix
, was die Ursache für die große Speichermenge ist, die von Ihrem Programm verwendet wird.Weitere Informationen
parfor
parfor
und den Zeitpunkt finden Sie unter "Entscheiden, wann verwendet werden soll " in der MATLAB-Dokumentation .quelle
parfor
der einzige Weg ? Die Verarbeitung funktioniert am besten, wenn ich sie so entworfen habe, da alles im Innerenparfor
CPU- und GPU-intensiv ist und somit die Leistung erheblich verbessert.parfor
. Wenn ja, dann ist es wahrscheinlich nützlich. - Wenn dies nicht der Fallslice_matrix
istgpuarray
, wird es möglicherweise nicht in die Zuordnung kopiert.slice_matrix
es kein istgpuArray
, bekomme ich immer noch ein Überlaufsymptom. Ich werde diese Frage offen lassen und sehen, ob es eine alternative Lösung gibt. Danke für die Antwort!Ich gehe davon aus, dass Ihr Code nur ein Beispielcode ist und
rand()
einen benutzerdefinierten Code in Ihrer MVE darstellt. Es gibt also einige Hinweise und Tricks für die Speichernutzung in matlab.Es gibt einen Ausschnitt aus den MathWorks-Schulungshandbüchern:
Als erstes müssen Sie die (Speicher-) Effizienz Ihres Codes überprüfen. Sogar der Code exzellenter Programmierer kann mit (ein wenig) Gehirnleistung weiter optimiert werden. Hier einige Hinweise zur Speichereffizienz
sum(X,2)
,mean(X,2)
,std(X,[],2)
bsxfun
x = 2*x+3
stattx = 2*x+3
Beachten Sie, dass das Optimum in Bezug auf die Speichernutzung nicht dasselbe ist, als ob Sie die Rechenzeit reduzieren möchten. Daher sollten Sie die Anzahl der Worker reduzieren oder die
parfor
-schleife nicht verwenden. (Daparfor
Shared Memory nicht verwendet werden kann, gibt es bei Verwendung der Parallel Toolbox keine Funktion zum Kopieren beim Schreiben .Wenn Sie sich Ihr Gedächtnis genauer ansehen möchten , was verfügbar ist und was von Matlab verwendet werden kann, lesen Sie
feature('memstats')
. Was ist für Sie interessant ist , ist die Virtual Memory , das istSchneller Seitenknoten : Matlab speichert Matrizen konsistent im Speicher. Für große Matrizen benötigen Sie einen großen Block freien Arbeitsspeichers. Dies ist auch der Grund, warum Sie Variablen zuweisen möchten, da Matlab durch dynamisches Ändern gezwungen wird, die gesamte Matrix jedes Mal an einen größeren Punkt im RAM zu kopieren, wenn sie aus dem aktuellen Punkt herauswächst.
Wenn Sie wirklich Speicherprobleme haben , möchten Sie vielleicht nur die Kunst der Datentypen kennenlernen - wie es in Sprachen niedrigerer Ebene erforderlich ist.
main_mat=zeros(500,500,2000,'single');
Zum Beispiel können Sie Ihre Speichernutzung halbieren, indem Sie direkt von Anfang an die Genauigkeit verwenden - übrigens funktioniert dies auch mitrand(...,'single')
und nativeren Funktionen - obwohl einige der komplexeren Matlab-Funktionen die Eingabe vom Typ double erfordern, was Sie können wieder ausgestoßen.quelle
Wenn ich das richtig verstehe, besteht Ihr Hauptproblem darin, dass
parfor
kein Speicher freigegeben werden kann. Stellen Sie sich jeden Parfor Worker als fast separate Matlab-Instanz vor.Grundsätzlich gibt es nur eine Problemumgehung, die ich kenne (die ich noch nie ausprobiert habe), nämlich "Shared Matrix" in Fileexchange: https://ch.mathworks.com/matlabcentral/fileexchange/28572-sharedmatrix
Weitere Lösungen: Wie andere vorgeschlagen haben: Parfor entfernen ist sicherlich eine Lösung, mehr RAM erhalten, große Arrays verwenden (die Festplatten verwenden, wenn der RAM voll ist, lesen Sie hier ), Operationen in kleinere Blöcke aufteilen, nicht zuletzt eine andere Alternative in Betracht ziehen als Matlab.
quelle
Sie können folgenden Code verwenden. Sie brauchen die Slice_Matrix eigentlich nicht
quelle