38,760
edits
No edit summary |
(Updating to match new version of source page) |
||
Line 138: | Line 138: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==== | ==== Building with OpenACC ==== | ||
<div class="mw-translate-fuzzy"> | |||
Choix du compilateur | |||
</div> | |||
|content= | |||
En date de mai 2021, plusieurs compilateurs offraient les fonctionnalités OpenACC. Puisque cette technologie est principalement soutenue par [http://www.nvidia.com/content/global/global.php NVidia] et [http://www.cray.com/ Cray], les compilateurs de ces deux compagnies offrent le meilleur support pour OpenACC. Les fonctionnalités OpenACC des compilateurs de [https://gcc.gnu.org/wiki/OpenACC GNU] s'améliorent depuis la version 5. | |||
<div class="mw-translate-fuzzy"> | |||
Dans ce tutoriel, nous utilisons la version 20.7 des compilateurs NVidia pour le calcul de haute performance. | |||
</div> | |||
The NVidia compilers use the <tt>-ta</tt> (target accelerator) option to enable compilation for an accelerator. We use the sub-option <tt>tesla:managed</tt>, to tell the compiler that we want it compiled for Tesla GPUs, and we want to use managed memory. Managed memory simplifies the process of transferring data to and from the device. We will remove this option in a later example. We also use the option <tt>-fast</tt>, which is an optimization option. | |||
{{Command | {{Command | ||
Line 160: | Line 170: | ||
34, Loop is parallelizable | 34, Loop is parallelizable | ||
}} | }} | ||
As we can see in the compiler output, the compiler could not parallelize the two loops. We will see in the following sections how to deal with this. | As we can see in the compiler output, the compiler could not parallelize the two loops. We will see in the following sections how to deal with this. | ||
== Réparer les fausses dépendances de boucles == | == Réparer les fausses dépendances de boucles == | ||
Même lorsque le programmeur sait qu'une boucle peut être parallélisée, il arrive que le compilateur ne le remarque pas. Un cas commun en C/C++ est connu sous le nom de [https://en.wikipedia.org/wiki/Pointer_aliasing ''pointer aliasing'']. Contrairement au Fortran, C/C++ ne possèdent pas comme tel de tableaux (''arrays''), mais plutôt des pointeurs. Le concept d'alias s'applique à deux pointeurs dirigés vers la même mémoire. Si le compilateur ne sait pas que des pointeurs ne sont pas des alias, il doit cependant le supposer. Dans l'exemple précédent, on voit clairement pourquoi le compilateur ne pouvait pas paralléliser la boucle. En supposant que les pointeurs sont identiques, il y a forcément dépendance des itérations de la boucle. | Même lorsque le programmeur sait qu'une boucle peut être parallélisée, il arrive que le compilateur ne le remarque pas. Un cas commun en C/C++ est connu sous le nom de [https://en.wikipedia.org/wiki/Pointer_aliasing ''pointer aliasing'']. Contrairement au Fortran, C/C++ ne possèdent pas comme tel de tableaux (''arrays''), mais plutôt des pointeurs. Le concept d'alias s'applique à deux pointeurs dirigés vers la même mémoire. Si le compilateur ne sait pas que des pointeurs ne sont pas des alias, il doit cependant le supposer. Dans l'exemple précédent, on voit clairement pourquoi le compilateur ne pouvait pas paralléliser la boucle. En supposant que les pointeurs sont identiques, il y a forcément dépendance des itérations de la boucle. | ||
<div class="mw-translate-fuzzy"> | |||
===Mot-clé <tt>restrict</tt> === | ===Mot-clé <tt>restrict</tt> === | ||
Une des manières de dire au compilateur que les pointeurs '''ne sont pas''' des alias est d'utiliser le mot-clé <tt>restrict</tt>, introduit à cette fin dans C99. Il n'y a toujours pas de manière standard pour ce faire en C++, mais chaque compilateur possède un mot-clé qui lui est propre. Dépendant du compilateur, on peut utiliser <tt>__restrict</tt> ou <tt>__restrict__</tt>. Les compilateurs du Portland Group utilisent <tt>__restrict</tt>. Pour savoir pourquoi il n'existe pas de standard en C++, consultez [http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3988.pdf ce document]. Ce concept est important pour OpenACC comme pour toute programmation C/C++, car les compilateurs peuvent effectuer plusieurs autres optimisations si les pointeurs ne sont pas des alias. Remarquez que le mot-clé se place '''après''' le pointeur puisque c'est à ce dernier qu'il se réfère, et non au type; autrement dit, la déclaration doit se lire <code>float * __restrict A;</code> plutôt que <code>float __restrict * A;</code>. | Une des manières de dire au compilateur que les pointeurs '''ne sont pas''' des alias est d'utiliser le mot-clé <tt>restrict</tt>, introduit à cette fin dans C99. Il n'y a toujours pas de manière standard pour ce faire en C++, mais chaque compilateur possède un mot-clé qui lui est propre. Dépendant du compilateur, on peut utiliser <tt>__restrict</tt> ou <tt>__restrict__</tt>. Les compilateurs du Portland Group utilisent <tt>__restrict</tt>. Pour savoir pourquoi il n'existe pas de standard en C++, consultez [http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3988.pdf ce document]. Ce concept est important pour OpenACC comme pour toute programmation C/C++, car les compilateurs peuvent effectuer plusieurs autres optimisations si les pointeurs ne sont pas des alias. Remarquez que le mot-clé se place '''après''' le pointeur puisque c'est à ce dernier qu'il se réfère, et non au type; autrement dit, la déclaration doit se lire <code>float * __restrict A;</code> plutôt que <code>float __restrict * A;</code>. | ||
</div> | |||
Line 182: | Line 187: | ||
En déclarant un pointeur comme étant ''restreint'', on s'assure qu'uniquement ce pointeur ou une valeur dérivée (comme <tt>ptr +1</tt>) pourra accéder à l'objet auquel il réfère, et ce pour la durée de vie du pointeur. Ceci est une garantie que le programmeur donne au compilateur; si le programmeur manque à son obligation, le comportement n'est pas défini. Pour plus d'information, consultez l'article Wikipédia [https://en.wikipedia.org/wiki/Fstab restrict]. | En déclarant un pointeur comme étant ''restreint'', on s'assure qu'uniquement ce pointeur ou une valeur dérivée (comme <tt>ptr +1</tt>) pourra accéder à l'objet auquel il réfère, et ce pour la durée de vie du pointeur. Ceci est une garantie que le programmeur donne au compilateur; si le programmeur manque à son obligation, le comportement n'est pas défini. Pour plus d'information, consultez l'article Wikipédia [https://en.wikipedia.org/wiki/Fstab restrict]. | ||
}} | }} | ||
=== Boucle avec clause <tt>independent</tt> === | === Boucle avec clause <tt>independent</tt> === |