Ao atribuir uma matriz a uma memória alocada muito maior, o matlab de alguma forma a duplicará enquanto a 'copia' e, se a matriz a ser copiada for grande o suficiente, haverá excesso de memória. Este é o código de exemplo:
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
Alguma maneira de simplesmente 'esmagar' o slice_matrix
para o main_mat
sem a sobrecarga? Desde já, obrigado.
EDITAR:
O estouro ocorreu quando main_mat
é alocado previamente. Se main_mat
for inicializado com main_mat=zeros(500,500,1);
(tamanho menor), o estouro não ocorrerá, mas diminuirá a velocidade, pois a alocação não é feita antes que a matriz seja atribuída a ela. Isso reduzirá significativamente o desempenho conforme o intervalo de k
aumentos.
matlab
optimization
Gregor Isack
fonte
fonte
parfor
loop para fins de otimização . Além disso,parfor
copia seus dados para cada trabalhador separado, supondo que 4 trabalhadores dupliquem seus dados quatro vezes na RAM.memory
função? O gerente de tarefas? Um erro de memória do Matlab? Em que linha de código está acontecendo?main_mat(:,:,1+(k-1)*n:1+(k-1)*n+n-1)
é onde ocorre o problema de estouro de memória. É verificado quando eu aloquei omain_mat
antemão, ele irá estourar, se não o fizer, não. O Matlab retornará 'erro de falta de memória'.h=h+slice_matrix(end)
antes demain_mat(:,:,1+(k-1)*n:1+(k-1)*n+n-1)=slice_matrix;
(e inicializar h com 0)? Suspeito que esta nova linha adicionada já cause problemas de memória.Respostas:
A questão principal é que os números ocupam mais espaço que zeros. consome
main_mat=zeros(500,500,2000);
pouca RAM emain_mat = rand(500,500,2000);
consome muito, não importa se você usa GPU ou parfor (na verdade, o parfor fará com que você use mais RAM). Portanto, este não é um inchaço artificial da memória. Seguindo o link de Daniel abaixo, parece que a atribuição de zeros cria apenas ponteiros para a memória, e a memória física é preenchida apenas quando você usa a matriz para "números". Isso é gerenciado pelo sistema operacional. E isso é esperado para Windows, Mac e Linux, seja com Matlab ou com outros idiomas como C.fonte
zeros
toda a memória virtual é realmente alocada, mas nenhuma memória é usada.whos
mostra o mesmo tamanho para ambas as matrizes, enquanto meu sistema operacional mostra um consumo de memória diferente. Excluí meu comentário porque sua resposta definitivamente não está errada.ones
vez dezeros
, isso garante que a memória seja realmente alocada no momento da chamada da respectiva função.main_mat
são atribuídos valores diferentes de zero. Anteriormente, apenas a memória virtual (espaço de endereço) era atribuída, agora é atribuída à memória física.A remoção
parfor
provavelmente corrigirá seu problema.parfor
não é útil lá. O MATLABparfor
não usa paralelismo de memória compartilhada (ou seja, não inicia novos threads), mas sim paralelismo de memória distribuída (inicia novos processos). Ele foi projetado para distribuir trabalho por um conjunto ou nós de trabalho. E, embora também funcione em um nó (ou em um único computador desktop) para distribuir o trabalho em vários núcleos, não é uma maneira ideal de fazer paralelismo em um nó.Isso significa que cada um dos processos iniciados por
parfor
precisa ter sua própria cópiaslice_matrix
, o que é a causa da grande quantidade de memória usada pelo seu programa.Consulte "Decidir quando usar
parfor
" na documentação do MATLAB para saber mais sobreparfor
e quando usá-lo.fonte
parfor
é a única maneira ? O processamento funciona melhor quando eu o projetei dessa maneira, uma vez que tudo dentroparfor
é intensivo em CPU e GPU, portanto, melhorou significativamente o desempenho.parfor
. Se sim, então sim, é provavelmente útil. - Talvez, seslice_matrix
não for umgpuarray
, não seja copiado na tarefa.slice_matrix
não seja umgpuArray
, eu ainda estou com um sintoma de transbordamento. Vou deixar essa pergunta em aberto, vamos ver se há alguma solução alternativa. Obrigado pela resposta!Presumo que seu código seja apenas um exemplo de código e que
rand()
represente um costume no seu MVE. Portanto, existem algumas dicas e truques para o uso da memória no matlab.Há um trecho dos manuais de treinamento do MathWorks:
A primeira coisa a fazer seria verificar a eficiência (memória) do seu código. Até o código de excelentes programadores pode ser otimizado ainda mais com (um pouco) poder do cérebro. Aqui estão algumas dicas sobre eficiência de memória
sum(X,2)
,mean(X,2)
,std(X,[],2)
bsxfun
x = 2*x+3
vez dex = 2*x+3
Esteja ciente de que o melhor em relação ao uso da memória não é o mesmo como se você desejasse reduzir o tempo de computação. Portanto, convém reduzir o número de trabalhadores ou deixar de usar o
parfor
loop. (Comoparfor
não é possível usar a memória compartilhada, não há recurso de copiar na gravação usando o Parallel Toolbox.Se você deseja examinar mais de perto sua memória , o que está disponível e pode ser usado pelo Matlab, confira
feature('memstats')
. O que é interessante para você é a memória virtual que éNó lateral rápido : o Matlab armazena matrizes de forma consistente na memória. Você precisa ter um grande bloco de RAM livre para matrizes grandes. Essa também é a razão pela qual você deseja alocar variáveis, porque alterá-las dinamicamente força o Matlab a copiar toda a matriz para um ponto maior na RAM toda vez que ele ultrapassa o ponto atual.
Se você realmente tem problemas de memória , pode apenas querer explorar a arte dos tipos de dados - como é necessário nos idiomas de nível inferior. Por exemplo, você pode reduzir o uso de memória pela metade usando precisão única diretamente desde o início
main_mat=zeros(500,500,2000,'single');
- aliás, isso também funciona comrand(...,'single')
e mais funções nativas - embora algumas das funções mais sofisticadas do matlab exijam entrada do tipo double, que você pode upcast novamente.fonte
Se bem entendi, o seu problema principal é que
parfor
não permite compartilhar memória. Pense em cada parfor worker como quase uma instância separada do matlab.Basicamente, existe apenas uma solução alternativa para isso que eu conheço (que nunca tentei), que é 'matriz compartilhada' no Fileexchange: https://ch.mathworks.com/matlabcentral/fileexchange/28572-sharedmatrix
Mais soluções: como outros sugeriram: remover o parfor é certamente uma solução, obtenha mais memória RAM, use matrizes altas (que usam discos rígidos quando a memória RAM está cheia, leia aqui ), divida operações em partes menores, por último, mas não menos importante, considere uma alternativa diferente de Matlab.
fonte
Você pode usar o seguinte código. Você realmente não precisa do slice_matrix
fonte