4 votes

Erreur lors de l'utilisation de parfor (parallel for loop) dans MATLAB

J'ai affaire à une très grande matrice et je voulais donc utiliser le calcul parallèle dans MATLAB pour l'exécuter en grappes. Ici, j'ai créé une matrice éparse en utilisant :

Ad = sparse(length(con)*length(uni_core), length(con)*length(uni_core));

J'ai une fonction écrite adj à l'aide de laquelle je peux remplir la matrice Ad . Chaque fois que la boucle s'exécute, à partir de la fonction adj J'obtiens une matrice symétrique carrée qui doit être affectée à l'élément Ad de 3682*(i-1)+1 à 3682 *(i-1)+3682 dans le premier indice et de la même manière dans le deuxième indice. Ceci est illustré ici :

parfor i = 1:length(con)
  Ad((3682*(i-1))+1:((3682*(i-1))+3682), ...
     (3682*(i-1))+1:((3682*(i-1))+3682)) = adj(a, b, uni_core);
end

Dans une boucle for normale, il fonctionne sans problème. Mais dans une boucle parfor en calcul parallèle, je reçois une erreur indiquant qu'il y a un problème dans l'utilisation des tableaux découpés en tranches avec parfor .

5voto

Edric Points 11387

Les sorties des boucles PARFOR doivent être soit des variables de réduction (par exemple, calcul d'une somme), soit des "tranches". Voir cette page dans le document pour en savoir plus.

Dans votre cas, vous essayez de former une sortie "découpée", mais votre expression d'indexation est trop compliquée pour PARFOR. Dans une PARFOR, une sortie découpée doit être indexée par : la variable de boucle pour un indice, et par une expression constante pour les autres indices. L'expression constante doit être soit : , end ou un scalaire littéral. L'exemple suivant montre plusieurs sorties en tranches :

x3 = zeros(4, 10, 3);
parfor ii = 1:10
    x1(ii) = rand;
    x2(ii,:) = rand(1,10);
    x3(:,ii,end) = rand(4,1);
    x4{ii} = rand(ii);
end

Dans votre cas, votre expression d'indexation dans Ad est trop compliquée pour être gérée par PARFOR. La chose la plus simple que vous puissiez faire est de renvoyer les calculs sous la forme d'un tableau de cellules, puis de les injecter dans Ad du côté de l'hôte à l'aide d'une boucle FOR normale, comme suit :

parfor i = 1:length(con)
   tmpout{i} = ....;
end
for i = 1:length(con)
   Ad(...) = tmpout{i};
end

4voto

gnovice Points 70970

Edric a déjà expliqué pourquoi vous obtenez une erreur, mais je voulais faire une autre suggestion de solution. La matrice Ad que vous créez est constitué d'une série de blocs de 3682 par 3682 le long de la diagonale principale, avec des zéros partout ailleurs. Une solution consiste à créer d'abord vos blocs dans un fichier PARFOR en les stockant dans un tableau de cellules. Vous pouvez ensuite les combiner en une seule matrice en appelant la fonction BLKDIAG :

cellArray = cell(1,length(con));  %# Preallocate the cell array
parfor i = 1:length(con)
  cellArray{i} = sparse(adj(a,b,uni_core));  %# Compute matrices in parallel
end
Ad = blkdiag(cellArray{:});

La matrice résultante Ad sera clairsemée, car chaque bloc a été converti en un matrice éparse avant d'être placé dans le tableau de cellules.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X