En affectant une matrice à une mémoire allouée beaucoup plus grande, matlab la dupliquera d'une manière ou d'une autre tout en la «copiant», et si la matrice à copier est suffisamment grande, il y aura un dépassement de mémoire. Voici l'exemple de code:
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
Est-il possible de simplement `` casser '' le slice_matrix
sur le main_mat
sans les frais généraux? Merci d'avance.
ÉDITER:
Le débordement s'est produit lors de l' main_mat
allocation préalable. Si main_mat
est initialisé avec main_mat=zeros(500,500,1);
(taille plus petite), le débordement ne se produira pas, mais il sera ralenti car l'allocation n'est pas effectuée avant que la matrice ne lui soit affectée. Cela réduira considérablement les performances à mesure que la plage d' k
augmentations.
matlab
optimization
Gregor Isack
la source
la source
parfor
boucle à des fins d'optimisation . De plus,parfor
copie vos données sur chaque travailleur distinct, supposant ainsi que 4 travailleurs dupliquent vos données quatre fois dans la RAM.memory
fonction? Le gestionnaire de tâches? Une erreur de mémoire de Matlab? À quelle ligne de code se produit-il?main_mat(:,:,1+(k-1)*n:1+(k-1)*n+n-1)
c'est là que se produit le problème de débordement de mémoire. C'est vérifié quand j'ai alloué lemain_mat
pré, ça va déborder, si je ne le fais pas, ça ne va pas. Matlab renverra «erreur de mémoire insuffisante».h=h+slice_matrix(end)
avantmain_mat(:,:,1+(k-1)*n:1+(k-1)*n+n-1)=slice_matrix;
(et initialiser h avec 0)? Je soupçonne que cette ligne nouvellement ajoutée entraînera déjà des problèmes de mémoire.Réponses:
Le problème principal est que les nombres prennent plus de place que les zéros.
main_mat=zeros(500,500,2000);
prend peu de RAM tout en enmain_mat = rand(500,500,2000);
prend beaucoup, peu importe si vous utilisez GPU ou parfor (en fait, parfor vous fera utiliser plus de RAM). Ce n'est donc pas un gonflement artificiel de la mémoire. En suivant le lien de Daniel ci-dessous, il semble que l'affectation de zéros ne crée que des pointeurs vers la mémoire, et la mémoire physique n'est remplie que lorsque vous utilisez la matrice pour les "nombres". Ceci est géré par le système d'exploitation. Et il est prévu pour Windows, Mac et Linux, que vous le fassiez avec Matlab ou d'autres langues telles que C.la source
zeros
toute la mémoire virtuelle est réellement allouée, mais aucune mémoire n'est utilisée.whos
montre la même taille pour les deux matrices, tandis que mon os montre une consommation de mémoire différente. J'ai supprimé mon commentaire car votre réponse n'est certainement pas fausse.ones
au lieu dezeros
, cela garantit que la mémoire est réellement allouée au moment d'appeler la fonction respective.main_mat
valeurs non nulles sont attribuées. Auparavant, seule la mémoire virtuelle (espace d'adressage) était affectée, elle est désormais affectée à la mémoire physique.La suppression résoudra
parfor
probablement votre problème.parfor
n'y est pas utile. MATLABparfor
n'utilise pas le parallélisme de mémoire partagée (c'est-à-dire qu'il ne démarre pas de nouveaux threads) mais plutôt le parallélisme de mémoire distribué (il démarre de nouveaux processus). Il est conçu pour distribuer le travail sur un ensemble ou des nœuds de travail. Et bien qu'il fonctionne également au sein d'un nœud (ou d'un seul ordinateur de bureau) pour distribuer le travail sur plusieurs cœurs, ce n'est pas un moyen optimal de faire du parallélisme au sein d'un nœud.Cela signifie que chacun des processus démarrés par
parfor
doit avoir sa propre copie deslice_matrix
, ce qui est la cause de la grande quantité de mémoire utilisée par votre programme.Voir "Décider quand utiliser
parfor
" dans la documentation MATLAB pour en savoir plusparfor
et quand l'utiliser.la source
parfor
est-il le seul moyen ? Le traitement fonctionne mieux lorsque je l'ai conçu de cette façon, car tout à l'intérieurparfor
est gourmand en CPU et en GPU, il a donc considérablement amélioré les performances.parfor
. Si oui, alors oui, c'est probablement utile. - Peut-être que si ceslice_matrix
n'est pas le cas,gpuarray
il ne sera pas copié dans le devoir.slice_matrix
n'est pas le casgpuArray
, j'ai toujours un symptôme de débordement. Je vais laisser cette question ouverte, voyons s'il y a une autre solution. Merci pour la réponse!Je suppose que votre code n'est qu'un exemple de code et qu'il
rand()
représente une coutume dans votre MVE. Il y a donc quelques conseils et astuces pour l'utilisation de la mémoire dans matlab.Il y a un extrait des manuels de formation de MathWorks:
La première chose à faire serait de vérifier l'efficacité (mémoire) de votre code. Même le code d'excellents programmeurs peut être encore optimisé avec (un peu) la puissance du cerveau. Voici quelques conseils concernant l'efficacité de la mémoire
sum(X,2)
,mean(X,2)
,std(X,[],2)
bsxfun
x = 2*x+3
plutôt quex = 2*x+3
Sachez que l'optimisation de l'utilisation de la mémoire n'est pas la même chose que si vous souhaitez réduire le temps de calcul. Par conséquent, vous pouvez envisager de réduire le nombre de travailleurs ou de ne pas utiliser la
parfor
boucle. (Comme ilparfor
est impossible d'utiliser la mémoire partagée, il n'y a pas de fonction de copie sur écriture avec l'utilisation de Parallel Toolbox.Si vous voulez regarder de plus près votre mémoire , ce qui est disponible et qui peut être utilisé par Matlab, consultez
feature('memstats')
. Ce qui est intéressant pour vous, c'est la mémoire virtuelle qui estNoeud latéral rapide : Matlab stocke les matrices de manière cohérente en mémoire. Vous devez avoir un grand bloc de RAM libre pour les grandes matrices. C'est également la raison pour laquelle vous souhaitez allouer des variables, car les modifier dynamiquement oblige Matlab à copier la matrice entière vers un emplacement plus grand dans la RAM à chaque fois qu'elle dépasse le spot actuel.
Si vous avez vraiment des problèmes de mémoire , vous voudrez peut-être simplement creuser dans l'art des types de données - comme cela est requis dans les langues de niveau inférieur. Par exemple, vous pouvez réduire de moitié votre utilisation de la mémoire en utilisant la simple précision directement depuis le début
main_mat=zeros(500,500,2000,'single');
- btw, cela fonctionne également avecrand(...,'single')
et plus de fonctions natives - bien que certaines des fonctions matlab les plus sophistiquées nécessitent une entrée de type double, que vous pouvez refoulé.la source
Si je comprends bien, votre principal problème est qu'il
parfor
ne permet pas de partager la mémoire. Considérez chaque travailleur de parfor comme une instance matlab distincte.Il existe essentiellement une seule solution de contournement pour cela que je connais (que je n'ai jamais essayé), à savoir la `` matrice partagée '' sur Fileexchange: https://ch.mathworks.com/matlabcentral/fileexchange/28572-sharedmatrix
Plus de solutions: comme d'autres l'ont suggéré: supprimer parfor est certainement une solution, obtenir plus de RAM, utiliser des tableaux de grande taille (qui utilisent des disques durs lorsque le RAM est plein, lisez ici ), divisez les opérations en petits morceaux, enfin et surtout, envisagez une alternative autre que Matlab.
la source
Vous pouvez utiliser le code suivant. Vous n'avez en fait pas besoin de la slice_matrix
la source