Contenu principal

Cette page a été traduite par traduction automatique. Cliquez ici pour voir la dernière version en anglais.

Dépannage des variables dans les boucles parfor

Assurez-vous que les variables de boucle parfor sont des entiers croissants consécutifs

Les variables de boucle dans une boucle parfor doivent être des entiers consécutifs croissants. Pour cette raison, les exemples suivants renvoient des erreurs :

parfor i = 0:0.2:1      % not integers
parfor j = 1:2:11       % not consecutive
parfor k = 12:-1:1      % not increasing
Vous pouvez corriger ces erreurs en convertissant les variables de boucle en une plage valide. Par exemple, vous pouvez corriger l'exemple non entier comme suit :
iValues = 0:0.2:1;
parfor idx = 1:numel(iValues)
    i = iValues(idx);
    ...
end

Éviter les débordements dans les boucles parfor

Si MATLAB® détecte que la variable de boucle parfor peut déborder, il signale une erreur.

Condition de débordementExempleSolution

La longueur de la plage de boucle parfor dépasse la valeur maximale du type de variable de boucle.

Ici, MATLAB signale une erreur car length(-128:127)>maxint('int8') :

parfor idx=int8(-128:127)
    idx;
end

Utilisez un type de données plus grand pour la variable parfor-loop. Si vous souhaitez conserver le type de données d'origine dans vos calculs, convertissez la variable parfor-loop à l'intérieur de la boucle parfor.

parfor idx=-128:127
    int8(idx);
end

La valeur initiale de la plage de boucles parfor est égale à la valeur minimale du type de variable de boucle.

Ici, MATLAB signale une erreur car 0=intmin('uint32')  :

parfor idx=uint32(0:1)
    idx;
end

  • Utilisez un type de données plus grand avec une valeur minimale inférieure, comme dans la solution précédente.

  • Augmenter la plage de valeurs. Par exemple :

    parfor idx=uint32(0:1)+1
        idx-1;
    end

Résoudre les problèmes de classification des variables dans les boucles parfor

Lorsque MATLAB reconnaît un nom dans une boucle parfor comme une variable, la variable est classée dans l'une des nombreuses catégories, présentées dans le tableau suivant. Assurez-vous que vos variables sont classées de manière unique et répondent aux exigences de la catégorie. Les boucles parfor qui violent l'exigence renvoient une erreur.

ClassificationDescription
Variables de boucleIndices de boucle
Variables découpées en tranchesTableaux dont les segments sont exploités par différentes itérations de la boucle
Variables de diffusionVariables définies avant la boucle dont la valeur est requise à l'intérieur de la boucle, mais jamais affectée à l'intérieur de la boucle
Reduction VariablesVariables qui accumulent une valeur au fil des itérations de la boucle, quel que soit l'ordre d'itération
Variables temporairesVariables créées à l'intérieur de la boucle et non accessibles en dehors de la boucle

Pour savoir quelles variables vous avez, examinez le fragment de code. Toutes les classifications de variables dans le tableau sont représentées dans ce code :

Code fragment containing a parfor-loop in which each variable is labelled according to its classification.

Si vous rencontrez des problèmes de classification de variables, envisagez ces approches avant de recourir à la méthode plus difficile consistant à convertir le corps d'une boucle parfor en fonction.

  • Si vous utilisez une boucle for imbriquée pour indexer dans un tableau découpé, vous ne pouvez pas utiliser ce tableau ailleurs dans la boucle parfor. Le code de gauche ne fonctionne pas car A est découpé et indexé à l'intérieur de la boucle for imbriquée. Le code de droite fonctionne car v est attribué à A en dehors de la boucle imbriquée. Vous pouvez calculer une ligne entière, puis effectuer une seule affectation dans la sortie découpée.

    InvalideValide
    A = zeros(4, 10);
    parfor i = 1:4
        for j = 1:10
            A(i, j) = i + j;
        end
        disp(A(i, 1))
    end
    A = zeros(4, 10);
    parfor i = 1:4
        v = zeros(1, 10);
        for j = 1:10
            v(j) = i + j;
        end
        disp(v(1))
        A(i, :) = v;
    end

  • Le code de gauche ne fonctionne pas car la variable x dans parfor ne peut pas être classée. Cette variable ne peut pas être classée car il existe plusieurs affectations à différentes parties de x. Par conséquent, parfor ne peut pas déterminer s’il existe une dépendance entre les itérations de la boucle. Le code de droite fonctionne car vous écrasez complètement la valeur de x. parfor peut désormais déterminer sans ambiguïté que x est une variable temporaire.

    InvalideValide
    parfor idx = 1:10
        x(1) = 7;
        x(2) = 8;
        out(idx) = sum(x);
    end
    parfor idx = 1:10
        x = [7, 8];
        out(idx) = sum(x);
    end

  • Cet exemple montre comment découper le champ d'un tableau structuré. Voir struct pour plus de détails. Le code de gauche ne fonctionne pas car la variable a dans parfor ne peut pas être classée. Cette variable ne peut pas être classée car la forme d’indexation n’est pas valide pour une variable découpée. Le premier niveau d'indexation n'est pas l'opération d'indexation en tranches, même si le champ x de a semble être découpé correctement. Le code de droite fonctionne car vous extrayez le champ struct dans une variable séparée tmpx. parfor peut désormais déterminer correctement que cette variable est découpée. En général, vous ne pouvez pas utiliser les champs de struct ou les propriétés d'objets comme variables d'entrée ou de sortie découpées dans parfor.

    InvalideValide
    a.x = [];
    parfor idx = 1:10
        a.x(idx) = 7;
    end
    tmpx = [];
    parfor idx = 1:10
        tmpx(idx) = 7;
    end
    a.x = tmpx;

Tableaux de structures dans les boucles parfor

Créer des structures temporaires

Vous ne pouvez pas créer une structure dans une boucle parfor en utilisant l'affectation de notation par points. Dans le code de gauche, les deux lignes à l’intérieur de la boucle génèrent une erreur de classification. Dans le code de droite, comme solution de contournement, vous pouvez utiliser la fonction struct pour créer la structure dans la boucle ou dans le premier champ.

InvalideValide
parfor i = 1:4
    temp.myfield1 = rand();
    temp.myfield2 = i;
end
parfor i = 1:4
    temp = struct();
    temp.myfield1 = rand();
    temp.myfield2 = i;
end
parfor i = 1:4
    temp = struct('myfield1',rand(),'myfield2',i);
end

Champs de structure de découpage

Vous ne pouvez pas utiliser de champs de structure comme tableaux d'entrée ou de sortie découpés dans une boucle parfor En d’autres termes, vous ne pouvez pas utiliser la variable de boucle pour indexer les éléments d’un champ de structure. Dans le code de gauche, les deux lignes de la boucle génèrent une erreur de classification à cause de l'indexation. Dans le code de droite, comme solution de contournement pour la sortie découpée, vous utilisez des tableaux découpés séparés dans la boucle. Ensuite, vous attribuez les champs de structure une fois la boucle terminée.

InvalideValide
parfor i = 1:4
    outputData.outArray1(i) = 1/i;
    outputData.outArray2(i) = i^2;
end
parfor i = 1:4
    outArray1(i) = 1/i;
    outArray2(i) = i^2;
end
outputData = struct('outArray1',outArray1,'outArray2',outArray2);

La solution de contournement pour l'entrée découpée consiste à affecter le champ de structure à un tableau distinct avant la boucle. Vous pouvez utiliser ce nouveau tableau pour l’entrée découpée.

inArray1 = inputData.inArray1;
inArray2 = inputData.inArray2;
parfor i = 1:4
    temp1 = inArray1(i);
    temp2 = inArray2(i);
end

Conversion du corps d'une boucle parfor en fonction

Si tout le reste échoue, vous pouvez généralement résoudre les problèmes de classification de variables dans les boucles parfor en convertissant le corps de la boucle parfor en une fonction. Dans le code de gauche, Code Analyzer signale un problème avec la variable y, mais ne peut pas le résoudre. Dans le code de droite, vous résolvez ce problème en convertissant le corps de la boucle parfor en une fonction.

InvalideValide
function parfor_loop_body_bad
    data = rand(5,5);
    means = zeros(1,5);
    parfor i = 1:5
        % Code Analyzer flags problem 
        % with variable y below  
        y.mean = mean(data(:,i));
        means(i) = y.mean;
    end
    disp(means);
end
function parfor_loop_body_good
    data = rand(5,5);
    means = zeros(1,5);
    parfor i = 1:5
        % Call a function instead
        means(i) = computeMeans(data(:,i));
    end
    disp(means);
end

% This function now contains the body
% of the parfor-loop
function means = computeMeans(data)
    y.mean = mean(data);
    means = y.mean;
end
Starting parallel pool (parpool) using the 'Processes' profile ... connected to 4 workers.
    0.6786    0.5691    0.6742    0.6462    0.6307

Noms de variables sans ambiguïté

Si vous utilisez un nom que MATLAB ne peut pas distinguer sans ambiguïté en tant que variable à l'intérieur d'une boucle parfor, au moment de l'analyse, MATLAB suppose que vous faites référence à une fonction. Ensuite, au moment de l'exécution, si la fonction ne peut pas être trouvée, MATLAB génère une erreur. Voir Variable Names . Par exemple, dans le code suivant, f(5) pourrait faire référence soit au cinquième élément d'un tableau nommé f, soit à une fonction nommée f avec un argument de 5. Si f n'est pas clairement défini comme variable dans le code, MATLAB recherche la fonction f sur le chemin lorsque le code s'exécute.

parfor i = 1:n
    ...
    a = f(5);
    ...
end

Boucles parfor transparentes

Le corps d'une boucle parfor doit être transparent : toutes les références aux variables doivent être «visibles» dans le texte du code. Pour plus de détails sur la transparence, voir Ensure Transparency in parfor-Loops or spmd Statements .

Variables globales et persistantes

Le corps d'une boucle parfor ne peut pas contenir de déclarations de variables global ou persistent.

Voir aussi

Rubriques