Al asignar una matriz a una memoria asignada mucho más grande, matlab de alguna manera la duplicará mientras la 'copia', y si la matriz que se va a copiar es lo suficientemente grande, habrá un desbordamiento de memoria. Este es el código de muestra:
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
¿Alguna forma de simplemente 'aplastar' el slice_matrix
sobre main_mat
sin la sobrecarga? Gracias por adelantado.
EDITAR:
El desbordamiento se produjo cuando main_mat
se asigna de antemano. Si main_mat
se inicializa con main_mat=zeros(500,500,1);
(tamaño más pequeño), el desbordamiento no ocurrirá, pero se ralentizará ya que la asignación no se realiza antes de que se asigne la matriz. Esto reducirá significativamente el rendimiento a medida que k
aumenta el rango de aumento.
matlab
optimization
Gregor Isack
fuente
fuente
parfor
bucle para fines de optimización . Además,parfor
copia sus datos a cada trabajador por separado, suponiendo que 4 trabajadores dupliquen sus datos cuatro veces en RAM.memory
función? El administrador de tareas? ¿Un error de memoria de Matlab? ¿En qué línea de código está sucediendo?main_mat(:,:,1+(k-1)*n:1+(k-1)*n+n-1)
es donde ocurre el problema de desbordamiento de memoria. Se verifica cuando asigné demain_mat
antemano, se desbordará, si no lo hago, no lo hará. Matlab devolverá 'error de falta de memoria'.h=h+slice_matrix(end)
antes demain_mat(:,:,1+(k-1)*n:1+(k-1)*n+n-1)=slice_matrix;
(e inicializar h con 0)? Sospecho que esta línea recién agregada ya causará problemas de memoria.Respuestas:
El problema principal es que los números ocupan más espacio que los ceros.
main_mat=zeros(500,500,2000);
toma poca RAM mientrasmain_mat = rand(500,500,2000);
toma mucho, no importa si usa GPU o parfor (de hecho, parfor le hará usar más RAM). Entonces esto no es una hinchazón antinatural de la memoria. Siguiendo el enlace de Daniel a continuación, parece que la asignación de ceros solo crea punteros a la memoria, y la memoria física se llena solo cuando usa la matriz para "números". Esto es administrado por el sistema operativo. Y se espera para Windows, Mac y Linux, ya sea que lo haga con Matlab u otros lenguajes como C.fuente
zeros
toda la memoria virtual está realmente asignada, pero no se usa memoria.whos
muestra el mismo tamaño para ambas matrices, mientras que mi sistema operativo muestra un consumo de memoria diferente. Eliminé mi comentario porque su respuesta definitivamente no es incorrecta.ones
lugar dezeros
, esto asegura que la memoria esté realmente asignada al momento de llamar a la función respectiva.main_mat
se le asignan valores distintos de cero. Anteriormente solo se asignaba memoria virtual (espacio de direcciones), ahora se asigna a la memoria física.La eliminación
parfor
probablemente solucionará su problema.parfor
No es útil allí. MATLABparfor
no usa el paralelismo de memoria compartida (es decir, no inicia nuevos subprocesos) sino el paralelismo de memoria distribuida (inicia nuevos procesos). Está diseñado para distribuir el trabajo en un conjunto o nodos de trabajo. Y aunque también funciona dentro de un nodo (o una sola computadora de escritorio) para distribuir el trabajo en múltiples núcleos, no es una forma óptima de hacer paralelismo dentro de un nodo.Esto significa que cada uno de los procesos iniciados
parfor
debe tener su propia copiaslice_matrix
, que es la causa de la gran cantidad de memoria utilizada por su programa.Consulte "Decidir cuándo usar
parfor
" en la documentación de MATLAB para obtener más información acerca deparfor
cuándo usarlo.fuente
parfor
es la única forma ? El procesamiento funciona mejor cuando lo diseñé de esa manera, ya que todo en el interiorparfor
es intensivo en CPU y GPU, por lo que mejoró significativamente el rendimiento.parfor
. Si es así, entonces sí, es probable que sea útil. - Tal vez sislice_matrix
no es ungpuarray
no se copiará en la tarea.slice_matrix
no es ungpuArray
, sigo teniendo síntomas de desbordamiento. Dejaré esta pregunta abierta, veamos si hay alguna solución alternativa. Gracias por la respuesta sin embargo!Supongo que su código es solo un código de muestra y que
rand()
representa una costumbre en su MVE. Así que hay algunos consejos y trucos para el uso de memoria en matlab.Hay un fragmento de los manuales de capacitación de The MathWorks:
Lo primero que debe hacer es verificar la eficiencia (memoria) de su código. Incluso el código de excelentes programadores puede optimizarse aún más con (un poco) poder mental. Aquí hay algunos consejos sobre la eficiencia de la memoria.
sum(X,2)
,mean(X,2)
,std(X,[],2)
bsxfun
x = 2*x+3
lugar dex = 2*x+3
Tenga en cuenta que el uso óptimo de la memoria no es lo mismo que si quisiera reducir el tiempo de cálculo. Por lo tanto, es posible que desee considerar reducir la cantidad de trabajadores o abstenerse de usar el
parfor
bucle. (Comoparfor
no puede usar la memoria compartida, no hay una función de copia en escritura al usar Parallel Toolbox.Si desea ver más de cerca su memoria , qué está disponible y qué puede usar Matlab, consulte
feature('memstats')
. Lo que es interesante para usted es la memoria virtual que esNodo lateral rápido : Matlab almacena matrices consistentemente en la memoria. Necesita tener un gran bloque de RAM libre para matrices grandes. Esa es también la razón por la que desea asignar variables, porque cambiarlas dinámicamente obliga a Matlab a copiar toda la matriz en un punto más grande en la RAM cada vez que supera el punto actual.
Si realmente tiene problemas de memoria , es posible que solo desee profundizar en el arte de los tipos de datos, como se requiere en los idiomas de nivel inferior. Por ejemplo, puede reducir el uso de su memoria a la mitad utilizando precisión simple directamente desde el principio
main_mat=zeros(500,500,2000,'single');
, por cierto, esto también funciona conrand(...,'single')
más funciones nativas, aunque algunas de las funciones matlab más sofisticadas requieren la entrada de tipo double, que puede molesto de nuevo.fuente
Si entiendo correctamente, su problema principal es que
parfor
no permite compartir memoria. Piense en cada trabajador parfor como una instancia de matlab casi separada.Básicamente, solo sé una solución alternativa para esto (que nunca he probado), que es 'matriz compartida' en Fileexchange: https://ch.mathworks.com/matlabcentral/fileexchange/28572-sharedmatrix
Más soluciones: como sugirieron otros: eliminar parfor es sin duda una solución, obtener más ram, usar matrices altas (que usan discos duros cuando el ram se llena, lea aquí ), dividir las operaciones en trozos más pequeños, por último, pero no menos importante, considere una alternativa que no sea Matlab
fuente
Puede usar el siguiente código. En realidad no necesitas el slice_matrix
fuente