Dans les deux précédents articles sur Intel Parallel Studio, nous nous sommes intéressés aux outils Inspector et Amplifier qui permettent respectivement de corriger et accélérer vos logiciels parallèles. Mais nous n'avons pas encore abordé Composer, qui est le compilateur associé à diverses librairies comme Intel Threading Building Blocks et Intel Performance Primitives (TBB et IPP).
De nos jours, un compilateur ne peut se contenter de produire un binaire minimaliste, même optimisé. Il doit vous aider à adopter une syntaxe plus claire, apporter un éclairage nouveau sur votre code et surtout aider à paralléliser votre logiciel simplement. Un développeur n'est jamais trop exigeant avec son compilateur. Une fois Parallel Studio installé, pour utiliser le compilateur Intel il suffit de cliquer droit sur votre solution et demander sa conversion (la procédure est réversible). Il est important de noter que le compilateur et les librairies sont disponibles sur d’autres plates-formes, et que les performances sont bonnes sur d’autres processeurs que ceux d’Intel, portabilité avant tout ! Parmi toutes les fonctionnalités de Parallel Composer, parlons donc des différentes manières de paralléliser votre code, des extensions C++ d'Intel et des fonctions lambda.
OPENMP
OpenMP est un standard qui permet de paralléliser rapidement un code avec un minimum de changements par rapport à la version sérielle. Le standard existe depuis plus de 10 ans, il a prouvé son utilité dans le calcul scientifique et bénéficie d'un soutien sans faille de l'industrie ; vous pouvez donc l'utiliser en production sans crainte. Historiquement OpenMP a commencé par l'ajout de pragmas simples, ces commentaires très spéciaux lus par certains compilateurs. Par exemple une ligne "#pragma omp parallel for" placée juste avant une boucle for permet de la paralléliser. Différentes itérations de la boucle seront alors envoyées à différents threads (créés automatiquement par OpenMP), et ce de manière totalement transparente et dynamique lors de l'exécution. Vous pouvez même spécifier quel algorithme de distribution vous souhaitez, tout cela sans changer une seule ligne de code. Vous pouvez certes programmer des threads en bas niveau avec C/C++, mais pourquoi ne pas laisser faire la machine virtuelle OpenMP ? Connaître OpenMP c'est l'adorer !
Si votre compilateur ne comprend pas OpenMP, votre code sera compilé en sériel, donc aucun risque. Pour appliquer les instructions, il doit savoir mettre en place un cadre de calcul parallèle dynamique lors de l'exécution autour de votre code et de vos données, toute la complexité est donc reportée du développeur vers le compilateur. Tâche d'autant plus complexe que le standard, au début limité à de simples fonctions, permet maintenant la parallélisation de cas beaucoup plus complexes. Le support d'OpenMP dans sa version récente 3.0 devient donc un critère important lors du choix d'un compilateur. Dans sa mouture 3.0, OpenMP apporte notamment des améliorations dans la récursivité. Il n'est pas simple de paralléliser une liste de tâches dont on ne connaît pas l'étendue à l’avance, ou qui ont des dépen dances entre elles, deux caractéristiques de bien des algorithmes récursifs. Le nouveau concept de "Task" mettra une partie de votre code dans la liste d'attente des tâches à calculer en parallèle (que vous n'avez pas à gérer), quels que soient le nombre et la complexité des tâches ou la nature récursive de leurs appels.
EXTENSIONS INTEL C++
Le concept d'OpenMP réside dans l'usage de pragmas, annotations certes intelligentes et transparentes de votre code mais pas très respectueuses d'un style d'écriture "naturel" en C++. C'est pour cela qu'Intel propose l'emploi de nouvelles extensions C++ : vous pouvez écrire "__par" au lieu de "#pragma omp parallel for". Si le concept vous plaît, n'hésitez pas à le dire sur les forums de software.intel.com et nous étendrons ce type de mots clés a l'avenir.
VECTORISATION ET OOO
Nous parlons souvent de parallélisation au niveau logiciel dans le but d'utiliser différents coeurs, mais la parallélisation peut aussi se faire au niveau matériel dans l'utilisation simultanée de différentes unités de calcul d'un même coeur. Soit vous utilisez ces unités pour effectuer des calculs différents et indépendants, et c'est que vous avez un processeur "Out Of Order" (sans ordre déterminé). Soit vous les utilisez pour des calculs similaires sur des données différentes, nous parlons alors de vectorisation. Le calcul Out Of Order est une propriété de certains processeurs (dont les Core2 d'Intel) ou tout est géré automatiquement et de manière transparente, le compilateur intervient peu dans ce mécanisme. Par contre, la vectorisation nécessite l'emploi d'un jeu d'instructions spécifiques, les SSE (Streaming SIMD Extensions), LRBni (Larrabee New Instructions) ou futures Intel AVX (Advanced Vector eXtensions). Ces instructions sont généralement ajoutées par le compilateur si votre code le permet mais il vous faut lui en faire la demande par des arguments lors de la compilation (ces arguments peuvent être changés par des menus interactifs dans Visual Studio). Des exemples d'accélérations intéressantes concernent les opérations arithmétiques simples, ou l'emploi de "valarray".
DIAGNOSTIC
Par défaut, le compilateur Intel vous affichera un niveau de diagnostic comparable à celui de Visual Studio. Mais il est souvent très instructif de demander un affichage plus détaillé. Pour commencer, l'option "diagenable: level1" pourra déceler des incohérences comme des arguments incorrects ou des tests logiques inutiles. L'option "vec-report3" vous informera, elle, de la façon dont l'unité de vectorisation automatique du compilateur perçoit votre code, pas seulement le résultat de l'optimisation mais les raisons d'une non optimisation. Lorsque le compilateur ne peut déterminer avec certitude que deux données sont indépendantes, il suppose qu’elles sont dépendantes et empêche de vectoriser une boucle ou elles sont présentes. Bien souvent, de simples redéfinitions de variables temporaires permettent de prouver l’indépendance et de vectoriser. Et comme Parallel Composer est intégré à Visual Studio vous verrez les messages de log liés à votre code.
FONCTIONS LAMBDA
Si deux développeurs C++ se croisent ces derniers temps, il est probable que le sujet de discussion dérive rapidement vers les fonctions lambda. Probable aussi que la discussion soit quelque peu théorique, faute d'avoir un compilateur capable de les comprendre jusqu'à présent et une expérience pratique de ces fonctions. Pour résumer, une fonction lambda est une fonction déclarée à la volée lors de l'appel et dont la syntaxe est simplifiée. Si vous n'avez besoin d’une fonction qu'une seule fois, pourquoi la déclarer complètement et ne pas se concentrer sur son code utile à la place ? Présentées sous cet angle les fonctions lambda peuvent apparaître comme un léger raccourci syntaxique sans conséquences. Elles sont en fait une révolution dans le monde du C++ : elles marquent le passage d'une programmation procédurale vers une programmation fonctionnelle (en simplifiant). Ce n'est peut être pas tout à fait un hasard si Intel s'y intéresse de si près. Le support des fonctions lambda est demandé par nombre de développeurs et Intel se doit donc de l'incorporer dans le compilateur, mais plus généralement, la programmation fonctionnelle devrait à long terme permettre de tirer parti au mieux d'une architecture largement parallèle, et ce avec un code simple et naturel. La programmation fonctionnelle n'entre pas en concurrence avec des technologies de calcul parallèle comme OpenMP ou TBB (qui utilisent parfois des principes de programmation fonctionnelle), les deux approches sont complémentaires.
IPP
Lorsque vous voulez optimiser l'utilisation matérielle de votre logiciel, la première action à prendre est souvent de remplacer vos librairies par des librairies optimisées, parallèles et "thread safe" (dont le comportement en mode parallèle est garanti par le vendeur). Parallel Composer inclut la librairie Intel Performance Primitives ou IPP qui peut être distribuée gratuitement avec votre logiciel, ne vous privez donc pas de l'utiliser. IPP offre un panel de fonctions très large : codecs vidéo, traitement d'image, reconnaissance faciale et vocale, compression, cryptographie, ray tracing ainsi que des fonctions plus bas niveau de traitement de signal. Pour le traitement d'image par exemple, profitez du Deffered Mode Image Processing. Le DMIP vous propose de définir tous les filtres et opérations que vous souhaitez sur une image comme un pipeline avant de l'exécuter en optimisant l'utilisation du cache processeur. Utiliser un codec vidéo IPP dans votre logiciel offre une performance et une portabilité optimale assez simplement. Par contre, utiliser certaines fonctions de traitement de signal pour faire de la reconnaissance faciale est plus ardu. (Mais si ce sujet vous intéresse, la librairie Open Computer Vision est très amusante, plus facile à utiliser et disponible sous licence BSD). Si vous suivez l'actualité des processeurs de très près, vous avez peut être vu que le Core i7 "Nehalem" est sorti depuis peu et qu'il intègre un nouveau jeu d'instructions "STTNI" spécialisé dans le traitement de chaînes. Si vous travaillez dans la fouille de données profitez en dès maintenant avec des fonctions IPP comme "ippsFind*Any()". N'hésitez pas à regarder la documentation d'IPP, vous trouverez probablement des idées pour accélérer ou améliorer des parties de votre logiciel.
ET BIEN PLUS
Le compilateur Intel est déjà très complet et utile dans sa configuration actuelle avec OpenMP, IPP et TBB mais il le sera encore plus à l’avenir. Lorsque vous souhaiterez utiliser les ressources d'un accélérateur graphique comme Larrabee de manière transparente pour des simulations physiques ou une intelligence artificielle, il est fort possible que le compilateur joue un rôle central. Si vous voulez programmer en parallèle, en fonctionnel ou tout simplement créer des binaires plus rapides je vous encourage donc à tester Intel Parallel Composer et à donner votre avis sur les forums de software.intel.com.
Paul Guermonprez
Ingénieur logiciel Intel
Actualités
Intel Parallel Studio 2011 Getting Started
Pratique
Supplément C++
Livre blanc
Intel Parallel Studio 2011
Intel propose une nouvelle gamme d'outils de développement d'applications pour profiter du multicore via une programmation parallèle. Il s'agit de l'Intel® Parallel Studio qui d'adresse aux développeurs Windows qui possèdent Visual Studio* C/C++2008. Ce nouvel outil est en fait un ensemble qui réunit , Parallel Advisor pour diagnostiquer le code quant aux possibilités de parallélisation, Parallel Composer pour incorporer du parallélisme à l'aide d'un compilateur C++ Intel et des bibliothèques thread safe, Parallel Inspector pour découvrir des conflits de threading éventuels et Parallel Amplifier pour diagnostiquer le comportement des threads.
Liens
Actu
Pratique
Actu
Distributeurs INTEL