Le monde parallèle de Photoshop

Arnaud de la Grandière |
Voilà quinze ans que Photoshop a commencé à tirer parti des architectures multiprocesseurs. Le responsable technique de Photoshop chez Adobe répond aux question d'un ingénieur d'Intel : quelles perspectives de progression reste-t-il alors qu'on approche du plafond prédit par la loi d'Amdahl ?

Avec l'avènement des machines multiprocesseurs, on parle de plus en plus de calcul parallèle : le découpage d'une tâche en plusieurs afin de les exécuter simultanément sur plusieurs processeurs, pour tirer le meilleur parti du matériel.

Si Snow Leopard a mis l'exécution de code en parallèle sur le devant de la scène, avec Grand Central Dispatch et OpenCL, cette technique est pourtant assez ancienne. Elle était particulièrement mise à profit sur les serveurs (chaque tâche étant lancée par un client distinct, la mise en parallèle du code était relativement aisée). Cette architecture s'est retrouvée au sein de l'ordinateur de Monsieur Tout-le-Monde lorsque les fabricants de processeurs sont arrivés au bout de la course au mégahertz : l'augmentation de la cadence des processeurs devenait trop coûteuse et consommatrice d'énergie pour continuer à se justifier.

Mais dans le monde Mac, les machines multiprocesseurs remontent bien avant l'arrivée des processeurs Intel dans nos machines.

1996-apple-Powermac-9500


En 1995, Apple lancera le Power Macintosh 9500 dont un modèle inclut deux processeurs PowerPC cadencés à 180 MHz, succédé par le Power Macintosh 9600 équipé de deux processeurs à 200 MHz. En 1997, alors qu'Apple avait signé des accords de licence permettant à des constructeurs de fabriquer et vendre des machines compatibles avec Mac OS 8, la société Daystar avait mis sur le marché le Genesis MP, un "monstre" de puissance qui dépassait tout ce qui se faisait de mieux en Mac, à l'aide de quatre processeurs PowerPC 604e cadencés à 225 MHz. Plusieurs configurations de Power Mac G4 et G5 proposeront deux processeurs, le Power Mac G5 sera même équipé en bi-processeurs bi-cœurs en 2006.

Mais si les logiciels ont pu bénéficier de l'augmentation de la fréquence d'horloge des processeurs de manière automatique, sans avoir à être modifiés ou recompilés, les machines multiprocesseurs ne pouvaient être pleinement mises à profit qu'en modifiant les applications spécifiquement. Et en 1995, il n'y avait pas l'ombre d'un Mac OS X en vue, sans même parler de Grand Central Dispatch. Les développeurs étaient donc livrés à eux-mêmes pour tirer parti de ces monstres de puissance.

Un processeur surnuméraire qui ne fait qu'acte de présence

En conséquence, à l'époque bien peu nombreuses sont les applications qui ont été réécrites pour exploiter plus d'un processeur à la fois. Mais s'il est une application, entre toutes, qui peut gagner beaucoup à cette conversion, c'est bien Photoshop, avec ses calculs gourmands en puissance, d'autant plus que le calcul graphique se prête particulièrement bien au calcul parallèle. En effet, à son niveau le plus simple il suffit de diviser l'image sur laquelle on applique un filtre pour en distribuer chaque morceau à traiter par un processeur. Le logiciel à lui seul justifie l'achat de ces machines hors de prix : c'est d'ailleurs une chance, car peu d'autres applications exploitaient à l'époque plus d'un processeur. Photoshop est en conséquence un vétéran du calcul parallèle.

Mais à l'heure où les configurations octo-core, voire hexadéca-core (!) poignent à l'horizon, de nouveaux défis se profilent pour le logiciel d'édition graphique. Car ça n'est pas le tout de convertir certaines parties du code pour les adapter au calcul parallèle : à mesure de l'augmentation du nombre de processeurs, il faut proportionnellement augmenter le pourcentage de calcul parallèle pour continuer à en tirer des bénéfices sensibles. C'est un des enseignements de la loi d'Amdahl, du nom de l'ingénieur d'IBM qui l'a édictée.

Le plafond d'Amdahl

Et précisément, un code rendu parallèle à 50 % ne présentera plus d'accélération sensible entre 8 et 16 processeurs, comme établi sur le schéma ci-dessous.

648px-AmdahlsLaw.svg


Pour continuer à sentir la moindre accélération à chaque multiplication de processeurs, il faut donc convertir au parallélisme une partie de plus en plus importante du code, faute de quoi cette multiplication se fait en pure perte. Pour compliquer encore les choses, la multiplication des processeurs peut provoquer quelques congestions au niveau de l'accès à la mémoire vive, qui est partagée avec chacun d'entre eux : plus il y a de processeurs qui provoquent des lectures et écritures en mémoire, plus la RAM sera soumise à une charge qui deviendra difficile à soutenir, provoquant un effet de goulet d'étranglement.

Face à cette gageure, le site ACM a proposé à Clem Cole, architecte du programme Cluster Ready d'Intel, d'interroger Russell Williams, responsable scientifique de Photoshop, pour évoquer la quinzaine d'années de parallélisme dans Photoshop. Williams a précédemment travaillé chez Apple sur le microkernel de Copland (lire : Il y a 10 ans, la naissance agitée de Mac OS X), quant à Cole, il œuvre à mettre au point des méthodes avancées pour tirer le meilleur parti possible des architectures multiprocesseurs après s'être penché sur le kernel d'Unix.

Les deux spécialistes s'accordent pour dire que le calcul parallèle peut s'avérer particulièrement compliqué. Si le découpage d'une image permet des calculs parallèles relativement simples, c'est notamment parce qu'il ne nécessite pas de synchronisation des résultats. En effet, certaines opérations dépendant du résultat d'autres opérations, il faut prévoir tout un système de gestion des tâches, ce que Grand Central Dispatch prend désormais en charge sur Mac OS X.

Un bug joue à cache-cache pendant 10 ans

Une démonstration éloquente de la difficulté de cette tâche est donnée par Russell Williams : alors que l'équipe avait mis en parallèle diverses tâches simples (suivi du curseur, accès disques…), elle s'est frottée à un bug particulièrement récalcitrant : il aura fallu 10 ans à l'équipe pour parvenir à l'isoler et l'éradiquer. En effet, à l'inverse du code linéaire où il est facile de figer l'état du programme pour voir où le bât blesse, les calculs parallèles rendaient cette inspection impossible. Ces fonctions parallèles ont donc dû être désactivées durant tout ce temps. Jusqu'à ce qu'un ingénieur se rende compte, dix ans plus tard, que le problème venait de la différence entre Mac OS et Windows pour la commande de positionnement de l'index dans un fichier (un seul appel sur Mac et deux sur Windows), qui n'avait pas été correctement prise en compte lors de l'écriture du code.

Un tel problème serait plus simple à éradiquer aujourd'hui, avec l'évolution du C++ et des compilateurs notamment, qui prennent mieux en compte les problématiques liées au calcul parallèle, mais l'exemple illustre bien la difficulté induite par la segmentation des tâches : imaginez ce que ça peut donner s'il est question de passer 95 % du code en calcul parallèle pour atteindre le rendement maximum du graphique ci-dessus… Toujours est-il que l'équipe d'Adobe a dû essuyer les plâtres au fil des ans, se trouvant en première ligne pour découvrir ces problématiques et inventer une méthodologie.

Williams donne une autre illustration de ces problèmes : il est possible de piloter Photoshop pour des tâches répétitives par exemple à l'aide de JavaScript. Si les tâches répétitives se prêtent fort bien au calcul parallèle, les développeurs de Photoshop ne maitrisent absolument pas la structure des scripts réalisés par les utilisateurs finaux. Qui plus est, dans la plupart des cas les langages scripts sont éminemment linéaires de par nature. Pour mettre en parallèle ces opérations, il faudrait donc non seulement le faire de manière dynamique, mais qui plus est sur du code interprété, et donc non-compilé : un vrai casse-tête!

amdahl-bio-core-1-4-1


Quel recours pour l'avenir ?

La loi d'Amdahl est au cœur des préoccupations, puisqu'elle rationalise le rendement qu'on peut espérer d'une mise en parallèle des calculs : il faut prendre en considération d'une part l'accélération qu'on peut espérer d'une telle modification, mais également la quantité de travail nécessaire pour y parvenir. Williams se veut toutefois optimiste : les développeurs ont connu une crise similaire à la fin des années 70, alors qu'on s'inquiétait de la complexité des programmes, devenue ingérable pour le commun des mortels. C'est par touches successives que la situation s'est améliorée, avec des progrès structurels au sein des langages de programmation, comme par exemple la programmation orientée objet, ou encore de meilleures performances des compilateurs. Et de fait, le responsable d'Adobe a pu constater des améliorations de cet ordre pour le calcul parallèle dans les outils qu'il utilise au fil du temps, par exemple OpenGL ou OpenCL, permettant un niveau d'abstraction supérieur. Il demeure néanmoins difficile de débugger des programmes "multithread", plus encore lorsqu'on s'adresse à plus d'une plateforme matérielle, mais des outils tels que les TBB (Threading Building Blocks) permettent des avancées.

C'est par l'automatisation du processus que viendra le salut… du moins temporairement. Car malgré l'utilisation de bibliothèques parallèles, comme la transposition d'une image en fréquences, permettant ensuite l'utilisation de la transformée de Fourier rapide (une fonction très véloce de traitement du signal numérique) qu'on peut ensuite faire traiter par le GPU, le passage de bibliothèque en bibliothèque, le découpage forcené des algorithmes finit toujours par se heurter à la loi d'Amdhal, qui s'apparente de plus en plus à un mur infranchissable. Chaque interstice entre chaque étape provoque une perte de rendement, qui aboutit à un plafond quel que soit le nombre de processeurs qu'on ajoute et aussi optimisé que le programme puisse être. Si le passage à deux ou quatre processeurs a bien profité à Photoshop, la transition de huit à seize risque bien de passer inaperçue (lire Photoshop CS5 : plus de cœurs, moins de performances).

Ce constat étant posé, il faut réfléchir à de nouvelles architectures, tant matérielles que logicielles. Intel réfléchit notamment à des plateformes qui s'apparentent à des mini-clusters, en segmentant la mémoire vive pour en dédier chaque partie à un cœur, permettant ainsi d'éviter la saturation des entrées/sorties, ce qui équivaudrait en somme à plusieurs ordinateurs dans l'ordinateur. De son côté, Williams se montre peu intéressé par ces pistes, comme Larrabee (lire Larrabee : c'est où, dites ?), qui ne résolvent que des problèmes spécifiques alors que Photoshop est un logiciel dédié à un marché de masse : avec de tels investissements, hors de question de se limiter à un marché matériel encore hypothétique.

Adobe considère d'ailleurs que l'architecture actuelle continuera de représenter l'essentiel du marché, et compte continuer à s'investir dessus. Partant de là, la voie de recours passera par les processeurs graphiques, et des bibliothèques comme OpenCL, OpenGL et Pixel Bender. En tout état de cause, Williams ne se voit pas tirer parti de nouvelles architectures matérielles sans s'appuyer sur l'interface des systèmes d'exploitation. Ce qui revient à ce que les bibliothèques susnommées se chargent de la transition d'elles-mêmes, sans que les applications n'en soient particulièrement affectées.

La conversation à bâtons rompus entre les deux ingénieurs, aussi absconse qu'elle puisse être, n'en révèle pas moins l'inéluctable réalité : la multiplication des processeurs a permis de gagner un peu de temps avant d'arriver à bout du potentiel du silicium. La réduction de la gravure des processeurs se rapproche à chaque génération un peu plus de la taille de l'atome. Il faudra tôt ou tard changer de paradigme, et pour l'heure l'alternative est loin d'être prête. D'ici là, il faudra donc optimiser à tout crin pour que Photoshop continue à accomplir les tâches en moins de temps qu'il ne faut pour dire "dotriaconta-core".
avatar balmath | 
Très bon article. Il est clair qu'il est assez compliqué de debugger des programmes multi-threads. Le salut viendra peut-être d'un autre type de programmation...
avatar HAL-9000 | 
Premier article très bon depuis longtemps. - La question du multithread est complexe lorsqu'en effet, les calculs nécessitent d'être caclulée en quasi-même temps et que ceux-ci dépendent des uns des autres. - Remarque : bossant depuis plus d'un an sur le multithread (C++ notamment) et le cloud computing, on s'apperçoit que la problématique de calcul de temps se déplace avec les avancées du multithread : les temps de transferts de données entre GPU et processeur, entre serveur de données et ordinateur deviennent in fine plus long que les temps de calculs (qui ont été accélérés via le calcul parralèle). Le gain en temps se joue du coup sur plusieurs tableaux, et non sur l'aspect "multithreads".
avatar HAL-9000 | 
(pardon pour les fautes, impossible de reéditer sous IE8)
avatar Switcher | 
Excellent article. Un de plus.
avatar Anonyme (non vérifié) | 
Dans le 840 AV, il y avait déjà 2 processeurs. Certains filtres photoshop utilisaient le second (DSP) pour aller bien plus vite que le PPC601 qui équipait le PowerMac 6100.
avatar Goldevil | 
Les limites du silicium en terme de vitesse de traitement sont encore très loin d'êtres atteintes. Il ne faut pas oublier que nos processeurs sont basés sur de l'électronique synchrone, c'est-à-dire pilotés par une horloge. En gros, pour faciliter la conception du design, une horloge fixe a quel rythme tous les transistors peuvent changer d'état. C'est la vitesse du plus lent composant qui déterminera la vitesse maximum. En électronique asynchrone, tout fonctionne à sa vitesse maximum mais la complexité du design des puces augmente exponentiellement avec le nombre de transistors. Du coup on est toujours en logique synchrone mais on a multiplié le parallélisme et on parvient aussi à faire fonctionner différentes parties du processeurs à différente fréquences. Néanmoins, cela reste de gros blocs synchrones. Tout cela pour dire que ce n'est pas seulement de nouvelles méthodes de programmation mais aussi de nouvelles méthode de design de CPU que viendra le salut. PS: Il n'y a pas que le silicium. Il y a aussi le germanium, potentiellement plus performant mais beaucoup plus cher.
avatar Claude Pelletier | 
Cet article m'a passionné mais mon ignorance me joue des tours. Surtout quand le point final c'est "dotriaconta-core". Du coup je n'ai plus de cœur à l'ouvrage ……
avatar GillesB | 
Et l'optimisation du code dans tout cela???? Car quand on voit des monstres de puissance comme nos ordinateurs actuels qui sont à la peine pour simplement ouvrir un logiciel sans aucun fichier.... on peut se dire que les programmeurs, ont encore quelques années de boulot pour optimiser leurs créations. J'en veux pour preuve OS X qui gagne en perfs sur une même machine a chaque révision majeure.. ou presque.
avatar Arnaud de la Grandière | 
@ Thegambit : il y avait aussi des "cartes accélératrices" dédiées à Photoshop, mais ces processeurs étaient si spécialisés que leur cas est tout de même à part (et ça n'implique pas nécessairement de calcul parallèle, d'ailleurs).
avatar Anonyme (non vérifié) | 
Très bon article. Mais précisons tout de même que la loi d'Amdahl dit que la portion parallèle du code est mesurée en temps de calcul, et non en nombre de ligne de code (comme j'ai cru le comprendre dans votre article). Donc si on ne parallélise que 50% du code, mais que ce code est responsable de 95% du temps d'exécution, alors on va bien avoir un gain important entre 8 et 16 cœurs (courbe la plus haute du graphique).
avatar BioSS | 
GillesB > CS4 puis CS5 s'ouvrent beaucoup plus vite que leur prédecesseurs respectifs. Photoshop CS5 s'ouvre en moins de 3.5 secondes chez moi…
avatar Amonchakai | 
'comme la transposition d'une image en fréquences, permettant ensuite l'utilisation de la transformée de Fourier rapide (une fonction très véloce de traitement du signal numérique) qu'on peut ensuite faire traiter par le GPU,' wat?
avatar Nihao | 
C'est clair : bon article ! @GillesB : ben justement on voit là que l'optimisation de code ce n'est pas toujours très simple... il ne suffit pas de réécrire 3-4 lignes dans ce programme, si o veut vraiment paralléliser il faut souvent tout repenser ! De plus les programmes sont plus difficiles à debugger donc plus long à mettre au point donc plus cher à développer... @Goldevil : tout à fait d'accord, l'un des problème d'aujour'hui étant la dissipation thermique des processeurs, elle est réduite en gravant de plus en plus fin, mais elle sera réduite en désactivant des parties de puces, en utilisant des propriétés physiques peu exploiter encore (effet Pelletier, je ne sais quoi encore), etc ...
avatar ispeed | 
En gros ça veut dire, si vous avez un Macpro rev1 vous pouvez le garder très facilement encore 5 ans Les 12 coeurs et compagnie vendus aujourd'hui, reste purement du marketing :)
avatar poco | 
D'accord avec GillesB Quand je vois le temps que prennent OpenOffice, FileMaker, Mac OS etc... à se lancer sur mon MBP, je me dis qu'il doit bien y avoir 1000 autres solutions technologiques de faire un ordinateur qui sera bcp plus performant pour nous les communs des mortels, les 95% d'utilisateurs quoi ;-) J'attends toujours que les MBP démarrent comme mon iPhone ou ma Télévision. Le multi-cœur, multi-Processeurs est venu à mon avis, remplacer les arguments marketing de la vitesse du processeur des années 90. Mais au final, on n'y gagne rien ou presque. Et quand à vouloir améliorer notre quotidien, l'ergonomie de certains softs (OpenOffice par exemple, qui est ceci dit un soft indispensable pour tout utilisateur pro sur Mac) permettrait de gagner bcp plus de temps qu'avec du multi-proc. ;-))
avatar Weshouille | 
@ Claude : "dotriaconta-core" signifie 32 cœurs si mes renseignements sont bons
avatar Toumak | 
Vivent les langages de programmation fonctionnelle, tels Haskell ou Scala ! La programmation multithread s'avère infiniment plus simple avec ce type de langages qu'avec des langages plus traditionnels tels c++ et java.
avatar PA5CAL | 
"Quelles perspectives de progression reste-t-il alors qu'on approche du plafond prédit par la loi d'Amdahl ?" Question saugrenue, qui contient une affirmation inexacte. En effet, pour la majorité des traitements couramment parallélisable, comme notamment ceux effectués sur les images, le plafond correspondant à cette fameuse loi dépasse largement la dizaine de milliers de processeurs. Autant dire qu'on en est encore très loin. En revanche, comme le suggère l'article, la limite qui se fait jour se situe au niveau de l'architecture des interfaces, qui est actuellement inadaptée à une haute parallélisation. À quoi peut servir une armée de processeurs si elle passe son temps à attendre que les données à traiter lui arrivent ? C'est bien souvent ce qui se passe actuellement sur nos machines multiprocesseurs, une fois que les problèmes d'optimisation logicielle ont été réglés. La question d'Intel à Adobe est donc cruciale, et il ne faudrait pas que cette dernière réponde à côté.
avatar hawker | 
je suis aussi d'acc avec gilles B. Si les soft etaient simplement plus qualitatfis au niveau du code, les ordi serait plus puissant en consequence. Vrai que pour la transition ps cs4>ps cs5, les developpeurs on plutot bien bossé. Au reste de suivre et aux meilleurs de reussir... pourquoi linux est le plus utilisé pour les serveurs et les domaine tres pro a la pointe, parce que son code est tres qualitatif et bien plus performant a machine egale, et c'est deja par cette voie que devrai s'inspirer la concurrence et non toujours compter sur la puissance du matos. de toute façon, je pense simplement que le x86 commence vraiment a montrer ses limites, l'avenir passe par une toute nouvelle archi pour procos généralistes, qui pourra traiter du massivement parallèle conjointement a du non parallélisé ou peu... (et des nouveaux langages, api et outils) ça sera pas facile mais c'est un pallier qu'il faudra de toute façon franchir.

CONNEXION UTILISATEUR