Przypisując macierz do znacznie większej przydzielonej pamięci, Matlab w jakiś sposób powieli ją podczas „kopiowania”, a jeśli matryca do skopiowania jest wystarczająco duża, nastąpi przepełnienie pamięci. To jest przykładowy kod:
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
Każdy sposób, aby po prostu "rozbić zwanej dalej slice_matrix
na main_mat
bez obciążania? Z góry dziękuję.
EDYTOWAĆ:
Przepełnienie nastąpiło, gdy main_mat
zostało przydzielone wcześniej. Jeśli main_mat
zostanie zainicjowany za pomocą main_mat=zeros(500,500,1);
(mniejszy rozmiar), przepełnienie nie nastąpi, ale zostanie spowolnione, ponieważ alokacja nie zostanie wykonana przed przypisaniem do niej macierzy. Znacząco obniży to wydajność wraz ze k
wzrostem zakresu .
matlab
optimization
Gregor Isack
źródło
źródło
parfor
pętlę w celu optymalizacji . Dodatkowoparfor
skopiuj dane do każdego osobnego pracownika, zakładając, że 4 pracowników powiela dane cztery razy w pamięci RAM.memory
funkcji? Menedżer zadań? Błąd pamięci Matlaba? Przy jakiej linii kodu to się dzieje?main_mat(:,:,1+(k-1)*n:1+(k-1)*n+n-1)
występuje problem z przepełnieniem pamięci. Jest to weryfikowane, kiedy przydzieliłemmain_mat
wcześniej, przepełni się, jeśli nie, nie będzie. Matlab zwróci błąd braku pamięci.h=h+slice_matrix(end)
przedmain_mat(:,:,1+(k-1)*n:1+(k-1)*n+n-1)=slice_matrix;
(i zainicjować h za pomocą 0)? Podejrzewam, że ta nowo dodana linia już spowoduje problemy z pamięcią.Odpowiedzi:
Głównym problemem jest to, że liczby zajmują więcej miejsca niż zera.
main_mat=zeros(500,500,2000);
zajmuje niewiele pamięci RAM, amain_mat = rand(500,500,2000);
zajmuje dużo, bez względu na to, czy używasz GPU, czy parfor (w rzeczywistości, parfor sprawi, że będziesz używać więcej pamięci RAM). To nie jest nienaturalny obrzęk pamięci. Podążając za poniższym linkiem Daniela, wydaje się, że przypisanie zer tworzy tylko wskaźniki do pamięci, a pamięć fizyczna jest zapełniana tylko wtedy, gdy używasz macierzy dla „liczb”. Jest to zarządzane przez system operacyjny. Oczekuje się, że w systemach Windows, Mac i Linux, albo zrobisz to za pomocą Matlaba lub innych języków, takich jak C.źródło
zeros
cała pamięć wirtualna jest faktycznie przydzielana, ale pamięć nie jest używana.whos
pokazuje ten sam rozmiar dla obu macierzy, podczas gdy mój system operacyjny pokazuje inne zużycie pamięci. Usunąłem swój komentarz, ponieważ twoja odpowiedź zdecydowanie nie jest zła.ones
zamiast tegozeros
, dzięki temu pamięć zostanie faktycznie przydzielona w momencie wywołania odpowiedniej funkcji.main_mat
przypisuje się im niezerowe wartości. Wcześniej przypisywano tylko pamięć wirtualną (przestrzeń adresową), teraz jest ona przypisywana do pamięci fizycznej.Usunięcie
parfor
prawdopodobnie rozwiąże problem.parfor
nie jest tam przydatny. MATLABparfor
nie korzysta z równoległości pamięci współużytkowanej (tzn. Nie uruchamia nowych wątków), ale raczej z równoległości pamięci rozproszonej (uruchamia nowe procesy). Jest przeznaczony do rozdzielania pracy na zbiór lub węzły robocze. I chociaż działa również w obrębie jednego węzła (lub jednego komputera stacjonarnego), aby rozdzielić pracę na wiele rdzeni, nie jest to optymalny sposób wykonywania równoległości w obrębie jednego węzła.Oznacza to, że każdy proces uruchamiany przez
parfor
musi mieć własną kopięslice_matrix
, co jest przyczyną dużej ilości pamięci używanej przez program.Zobacz „Zdecyduj, kiedy używać
parfor
” w dokumentacji MATLAB, aby dowiedzieć się więcej o tymparfor
i kiedy z niego korzystać.źródło
parfor
to jedyny sposób ? Przetwarzanie działa najlepiej, gdy zaprojektowałem go w ten sposób, ponieważ wszystko w nimparfor
wymaga procesora i procesora graficznego, co znacznie poprawiło wydajność.parfor
. Jeśli tak, to tak, jest to prawdopodobnie przydatne. - Może jeślislice_matrix
nie jestgpuarray
, nie zostanie skopiowane w zadaniu.slice_matrix
nie jestgpuArray
, nadal mam objaw przepełnienia. Pozwolę otworzyć to pytanie, zobaczmy, czy jest jakieś alternatywne rozwiązanie. Dzięki za odpowiedź!Zakładam, że Twój kod to tylko przykładowy kod, który
rand()
reprezentuje niestandardowy kod w MVE. Jest więc kilka wskazówek i wskazówek dotyczących wykorzystania pamięci w Matlabie.Fragment podręczników szkoleniowych MathWorks zawiera fragment:
Pierwszą rzeczą do zrobienia byłoby sprawdzenie wydajności (pamięci) kodu. Nawet kod doskonałych programistów można później zoptymalizować za pomocą (niewielkiej) mocy mózgu. Oto kilka wskazówek dotyczących wydajności pamięci
sum(X,2)
,mean(X,2)
,std(X,[],2)
bsxfun
x = 2*x+3
zamiastx = 2*x+3
Należy pamiętać, że optymalne wykorzystanie pamięci nie jest takie samo, jakbyś chciał skrócić czas obliczeń. Dlatego warto rozważyć zmniejszenie liczby pracowników lub powstrzymanie się od używania
parfor
opcji -loop. (Ponieważparfor
nie można używać pamięci współdzielonej, nie ma funkcji kopiowania przy zapisie przy użyciu Parallel Toolbox.Jeśli chcesz bliżej przyjrzeć się swojej pamięci , co jest dostępne i które może być wykorzystane przez Matlab, sprawdź
feature('memstats')
. Co jest dla Ciebie interesujący jest pamięć wirtualna , która jestSzybki węzeł boczny : Matlab konsekwentnie przechowuje macierze w pamięci. Musisz mieć duży blok wolnej pamięci RAM dla dużych matryc. Jest to również powód, dla którego chcesz alokować zmienne, ponieważ ich dynamiczne wymuszanie powoduje, że Matlab kopiuje całą macierz do większego miejsca w pamięci RAM za każdym razem, gdy przerasta bieżące miejsce.
Jeśli naprawdę masz problemy z pamięcią , możesz po prostu zagłębić się w sztukę typów danych - tak jak jest to wymagane w językach niższego poziomu. Np. Możesz zmniejszyć zużycie pamięci o połowę, używając pojedynczej precyzji bezpośrednio od początku
main_mat=zeros(500,500,2000,'single');
- btw, działa to również zrand(...,'single')
i bardziej natywnymi funkcjami - chociaż kilka bardziej wyrafinowanych funkcji matlaba wymaga wprowadzenia typu double, co możesz znowu upcast.źródło
Jeśli dobrze rozumiem, twoim głównym problemem jest to, że
parfor
nie pozwala na współdzielenie pamięci. Pomyśl o każdym pracowniku jako prawie osobnej instancji Matlaba.Zasadniczo istnieje tylko jedno obejście tego, o czym wiem (którego nigdy nie próbowałem), czyli „wspólna matryca” w Fileexchange: https://ch.mathworks.com/matlabcentral/fileexchange/28572-sharedmatrix
Więcej rozwiązań: jak sugerują inni: usuń parfor to z pewnością jedno rozwiązanie, zdobądź więcej pamięci RAM, użyj wysokich macierzy (które używają dysków twardych, gdy pamięć RAM jest pełna, przeczytaj tutaj ), dziel operacje na mniejsze części, na koniec, rozważ także alternatywę inną niż Matlab.
źródło
Możesz użyć następującego kodu. W rzeczywistości nie potrzebujesz slice_matrix
źródło