Variables découpées en tranches
Une variable découpée est une variable dont la valeur peut être divisée en segments, ou tranches, qui sont ensuite exploités séparément par différents workers. Chaque itération de la boucle fonctionne sur une tranche différente du tableau. L’utilisation de variables découpées peut réduire la communication entre le client et les workers.
Dans cet exemple, les workers appliquent f aux éléments de A séparément.
parfor i = 1:length(A) B(i) = f(A(i)); end
Caractéristiques d'une variable découpée
Si une variable dans une boucle parfor possède toutes les caractéristiques suivantes, alors la variable est découpée :
Type d'indexation de premier niveau — Le premier niveau d'indexation est constitué soit de parenthèses,
(), soit d'accolades,{}.Liste d’index fixes — Dans les parenthèses ou les accolades de premier niveau, la liste des indices est la même pour toutes les occurrences d’une variable donnée.
Forme d’indexation — Dans la liste des indices de la variable, un seul index implique la variable de boucle.
Forme du tableau — Le tableau conserve une forme constante. Lors de l'affectation à une variable découpée en tranches, le côté droit de l'affectation ne peut pas être
[]ou'', car ces opérateurs tentent de supprimer des éléments.
Type d'indexation de premier niveau
Pour une variable découpée en tranches, le premier niveau d'indexation est placé entre parenthèses, (), ou entre accolades, {}.
Voici les formulaires pour le premier niveau d'indexation pour les tableaux qui sont découpés et non découpés.
| Non tranché | Tranché |
|---|---|
A.x | A(...) |
A.(...) | A{...} |
Après le premier niveau, vous pouvez utiliser n’importe quel type d’indexation MATLAB® valide dans le deuxième niveau et les niveaux suivants.
La variable A montrée ici à gauche n'est pas découpée ; celle montrée à droite est découpée.
A.q{i,12} A{i,12}.q
Liste d'index fixe
Dans l'indexation de premier niveau d'une variable découpée, la liste des indices est la même pour toutes les occurrences d'une variable donnée.
La variable A à gauche n'est pas découpée car A est indexée par i et i+1 à des endroits différents. Dans le code de droite, la variable A est découpée correctement.
| Non tranché | Tranché |
|---|---|
parfor i = 1:k B(:) = h(A(i), A(i+1)); end | parfor i = 1:k B(i) = f(A(i)); C(i) = g(A{i}); end |
L'exemple de droite montre des occurrences d'indexation de premier niveau utilisant à la fois des parenthèses et des accolades dans la même boucle, ce qui est acceptable.
L'exemple suivant à gauche ne découpe pas A car l'indexation de A n'est pas la même à tous les endroits. L'exemple de droite découpe à la fois A et B. L'indexation de A n'est pas la même que l'indexation de B . Cependant, l'indexation de A et B est cohérente individuellement.
| Non tranché | Tranché |
|---|---|
parfor i=1:10 b = A(1,i) + A(2,i) end | A = [ 1 2 3 4 5 6 7 8 9 10;
10 20 30 40 50 60 70 80 90 100];
B = zeros(1,10);
parfor i=1:10
for n=1:2
B(i) = B(i)+A(n,i)
end
end |
Forme d'indexation
Au premier niveau d'indexation d'une variable découpée, une seule expression d'indexation est de la forme i, i+k, i-k ou k+i. L'index i est la variable de boucle et k est une constante entière scalaire ou une variable de diffusion simple (non indexée). Toute autre expression d'indexation est une constante entière positive, une variable de diffusion simple (non indexée), une variable d'index de boucle for imbriquée, colon, une expression deux points impliquant des variables de diffusion simples ou des constantes entières scalaires, ou end.
Avec i comme variable de boucle, les variables A affichées à gauche ne sont pas découpées, tandis que les variables A affichées à droite sont découpées.
| Non tranché | Tranché |
|---|---|
A(i+f(k),j,:,3) % f(k) invalid for slicing A(i,:,s.field1) % s.field1 not simple broadcast var A(i,[20,21,30],end) % array literal not supported Avant R2024b : A(i,20:30,end) |
A(i+k,j,:,3)
A(i,:,end)
A(i,:,k)
A(i,20:30,end) (depuis R2024b) |
Vous pouvez contourner les expressions d’indexation non prises en charge en les déclarant comme variables de diffusion. Dans cet exemple, le code de gauche ne fonctionne pas car il utilise directement des expressions d’indexation non prises en charge pour indexer les variables de tranche. Le code de droite fournit une solution de contournement en déclarant les expressions comme variables de diffusion avant le corps de la boucle.
| Non tranché | Tranché |
|---|---|
parfor i = 1:n A(i, [false,true,true]) = 7; % not supported B(i, [20,21,30]) = 7; % also not supported end | b1 = [false,true,true]; b2 = [20,21,30]; parfor i = 1:n A(i,b1) = 7; % works B(i,b2) = 7; % also works end |
Lorsque vous utilisez d'autres variables avec la variable de boucle pour indexer un tableau, vous ne pouvez pas définir ces variables à l'intérieur de la boucle. En effet, ces variables sont constantes pendant toute l’exécution de l’instruction parfor. Vous ne pouvez pas combiner la variable de boucle avec elle-même pour former une expression d'index.
Forme du tableau
Une variable découpée en tranches doit conserver une forme constante. La variable A affichée ici n'est pas découpée :
A(i,:) = [];
A n'est pas découpé car modifier la forme d'un tableau découpé violerait les hypothèses régissant la communication entre le client et les workers.
Variables d'entrée et de sortie découpées
Une variable découpée peut être une variable d'entrée, une variable de sortie ou les deux. MATLAB transmet les variables d'entrée découpées du client aux workers et les variables de sortie découpées des workers au client. Si une variable est à la fois une entrée et une sortie, elle est transmise dans les deux sens.
Dans cette boucle parfor, A est une variable d'entrée découpée et B est une variable de sortie découpée.
A = rand(1,10); parfor ii = 1:10 B(ii) = A(ii); end
Cependant, si MATLAB détermine que, à chaque itération, les éléments variables découpés sont définis avant toute utilisation, alors MATLAB ne transmet pas la variable aux workers. Dans cet exemple, tous les éléments de A sont définis avant toute utilisation.
parfor ii = 1:n if someCondition A(ii) = 32; else A(ii) = 17; end % loop code that uses A(ii) end
Les variables de sortie découpées peuvent croître de manière dynamique grâce à des affectations indexées avec des valeurs par défaut insérées à des indices intermédiaires. Dans cet exemple, vous pouvez voir que la valeur par défaut de 0 a été insérée à plusieurs endroits dans A .
A = []; parfor idx = 1:10 if rand < 0.5 A(idx) = idx; end end disp(A);
0 2 0 4 5 0 0 8 9 10
Même si une variable découpée n'est pas explicitement référencée comme entrée, une utilisation implicite peut le rendre ainsi. Dans l'exemple suivant, tous les éléments de A ne sont pas nécessairement définis à l'intérieur de la boucle parfor. Par conséquent, les valeurs originales du tableau sont reçues, conservées, puis renvoyées depuis la boucle.
A = 1:10; parfor ii = 1:10 if rand < 0.5 A(ii) = 0; end end
Dans certaines circonstances, les boucles parfor doivent supposer qu'un worker peut avoir besoin de tous les segments d'une variable découpée. Dans cet exemple, il n'est pas possible de déterminer quels éléments de la variable découpée seront lus avant l'exécution, donc parfor envoie tous les segments possibles.
A = 1:10; parfor ii=1:11 if ii <= randi([10 11]) A(ii) = A(ii) + 1; end end
Boucles for imbriquées avec variables découpées
Lorsque vous indexez une variable découpée en tranches avec une variable de boucle for imbriquée, gardez ces exigences à l'esprit :
La variable découpée doit être incluse dans la boucle
forcorrespondante.Dans cet exemple, le code de gauche ne fonctionne pas car il indexe la variable découpée
Aen dehors de la boucleforimbriquée qui définitj.Non tranché Tranché A = zeros(10); parfor i=1:10 for j=1:10 end A(i,j)=1; end
A = zeros(10); parfor i=1:10 for j=1:10 A(i,j) = 1; end end
La plage de la variable
for-loop doit être un vecteur de lignes de nombres constants positifs ou de variables.Dans cet exemple, le code de gauche ne fonctionne pas car il définit la limite supérieure de la boucle
forimbriquée avec un appel de fonction. Le code de droite fournit une solution de contournement en définissant la limite supérieure dans une variable constante en dehors de la boucleparfor.Non tranché Tranché A = zeros(10); parfor i=1:10 for j=1:size(A,2) A(i,j)=1; end end
A = zeros(10); L = size(A,2); parfor i=1:10 for j=1:L A(i,j)=1; end end
La variable de boucle
forne doit pas être affectée autrement que par son instructionfor.Dans cet exemple, le code de gauche ne fonctionne pas car il réaffecte la variable
for-loop à l'intérieur de la bouclefor. Le code de droite fournit une solution de contournement en affectantià la variable temporairet.Non tranché Tranché A = zeros(10); parfor i=1:10 for j=1:10 if i == j j = i; A(i,j) = j; end end end
A = zeros(10); parfor i=1:10 for j=1:10 if i == j t = i; A(i,j) = t; end end end
Limitations des types de données
Certains types de données MATLAB ne prennent pas en charge l'utilisation comme variables d'entrée ou de sortie découpées pour une boucle
parfor. Pour utiliser une variable comme variable découpée, l'implémentationparfordoit pouvoir étendre la variable à l'aide de l'indexation.Les types de données suivants ne sont pas pris en charge en tant que variables découpées :
dictionarytable
Lorsque vous utilisez des tableaux découpés en tranches d'objets
handle, MATLAB construit des éléments par défaut. Pour plus d'informations, voir Create and Initialize Object Arrays.