Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

La programmation concurrente mieux adaptée aux CPU multi-coeurs ?
C'est ce que pense l'inventeur du XML

Le , par Idelways

0PARTAGES

0  0 
Lors d'une présentation à l'O'Reilly Open Source Convention 2010, Tim Bray, le co-inventeur du XML, a fortement plaidé pour la programmation concurrente et fonctionnelle.

Au lieu d'utiliser des threads, la programmation fonctionnelle présenterait, d'après lui, une meilleure approche pour les développeurs qui doivent réaliser des programmes pour les processeurs multi-coeurs

La programmation pour les CPU multi-coeurs amène en effet son lot de problèmes, au premier rang desquels la simultanéité. Ces nouveaux problèmes (dont les goulets d'étranglement), seraient des « problèmes très difficiles à appréhender ou à comprendre », a-t-il souligné.

La programmation fonctionnelle, paradigme des langages comme Erlang et Clojure, permettrait de mieux les solutionner, et donc de mieux gérer cette simultanéité.

La programmation fonctionnelle repose sur le principe que les données ne sont pas partagées. Conséquence, les développeurs n'ont pas à se soucier de savoir si elles changeront, ce qui « permet de désigner les données au lieu de les envoyer », souligne Bray.

Erlang (conçu pour la programmation massive des Switch téléphoniques avec des centaines voire des milliers de processeurs) est par exemple un langage qui n'a ni classes, ni objets, ni variables. Sa gestion des fichiers est « misérable ». Mais il resterait particulièrement approprié et puissant pour gérer le multi-coeur.

Idem pour Clojure, « un langage de très, très hautes performance » pour Bray. Clojure est un Lisp qui fonctionne sur la machine virtuelle Java et qui compile en code Java classique. Ses performances en terme de vitesse sont remarquables.

La thèse de la démonstration de Bray est de dire que gérer la simultanéité avec le threading n'est pas une mauvaise idée en soi. Mais cette programmation avec les threads (qui offre de multiples accès à partager, des données mutables, etc) est mal, voire pas du tout comprise.

Pire, elle « ne sera jamais comprise par les développeurs d'applications », provoque-t-il.

Faudrait-il donc tout revoir à zéro pour accompagner l'évolution du hardware ?

C'est un peu ce que pense Bill Dally, un des ingénieurs les plus importants de Nvidia, mais dans un registre différent lorsqu'il écrit dans Forbes « après 40 ans de programmation linéaire [il faudrait] une rupture avec les pratiques de longue date ».

Et de regretter le manque de formation des développeurs dans la programmation parallèle et les technologies propres aux multi-coeurs.

Deux visions pour un même constat : le multi-coeurs n'a pas fini d'être un défi pour les développeurs.

Source : Site de l'O'Reilly Open Source Convention 2010

Lire aussi :

Quel langage pour la JVM est pour vous promis à un bel avenir ?

Qu'est-ce qu'un langage fonctionnel

Les rubriques (actu, forums, tutos) de Développez :

Hardware
Langages

Et vous ?

Pratiquez-vous de la programmation concurrente ou fonctionnelle ?

Dans l'ère du multicoeurs, pensez-vous comme Bray que les paradigmes de programmation fonctionnelle et concurrente soit plus adaptés ?

En collaboration avec Gordon Fowler

Une erreur dans cette actualité ? Signalez-le nous !

Avatar de amaury pouly
Membre actif https://www.developpez.com
Le 27/07/2010 à 10:28
Citation Envoyé par unBonGars Voir le message
Programmation parralèle selon Intel : http://software.intel.com/en-us/parallel/
Pour ceux qui ont du temps devant eux !
Threads are evil : Avoid them ! (D. Richard Hipp sqLite)
The problem with threads (Edward A. Lee Berkeley) :
http://www.eecs.berkeley.edu/Pubs/TechRpts/2006/EECS-2006-1.pdf

Sinon, les telecoms se prètent très bien au multithread contrairement au reste.
La règle "Un thread = un device (telecom, GPU, sound, ...)" fonctionne pas trop mal.
En traitement de raw input : division du raw par le nombre de core : marche parfois aussi (sauf si agregation) (zip, flat, trt de signal)
SGBD : monothread obligatoire (voir titre).
Le reste est un casse tête à moins de faire "dormir" les threads pour.. imiter le monothread par synchronisation... J'espere que les core48 supporteront le turbo-boost.

D'accord avec ce qu'il dit, c'est même exactement ce que je dis aussi, sauf que ça ne dit pas qu'on pourra faire en parrallèle ce qu'on fait en séquentiel et personnellement j'en doute. Comme tout le monde l'exige, je ne demande qu'à apprendre mais parfois.. l'info n'est pas là !
Et la solution non plus..

Multicore et multi servers sont des disciplines très voisines pour le traitement. J'ai fait un peu des deux mais peut-être qu'un grand maître du multi-server pourrait donner quelques trucs et astuces....
Je dois voir le mal partout mais en quoi cet article est-il pertinent ? En gros il dit "les threads c'est mal" parce que c'est non-déterministe. Il dit aussi que le non-déterminisme c'est mal. Or certaines tâches sont non-déterministes. Si le code a une partie GUI et une partie calcul, une intervention de l'utilisateur est une action non-déterministe.

Je pense qu'on peut tourner le problème comme on veut, faire du message passing, faire des diagrammes et tout ce qu'on veut mais le problème fondamental c'est de faire plusieurs choses à la fois et cela nécessitera toujours de la synchronisation et donc il y aura un risque de bug.

On parle aussi beaucoup de la programmation fonctionnelle pour le calcul en parallèle et c'est vrai que c'est tentant étant donné que toutes les structures de données sont en lecture seulement. Toutefois, cela cache aussi ses propres problèmes. Par exemple, en fonctionnelle, tout est en lecture mais comme on écrit ? En créant des objets ! Or créer des objets demande de la mémoire qu'il faut allouer et libérer. Donc le problème n'a pas disparu.
Par ailleurs, on peut aussi perdre en performance puisque l'idée de la plupart des structures de données fonctionnelle c'est qu'on a l'intégralité de l'historique des modifications. En pratique cela veut dire que si on une structure A et qu'on veut la modifier pour obtenir B alors on représente B par représente A + modification. Autrement dit on se retrouve avec un empilement de modifications qui si elles ne sont pas bien faites seront moins performantes.
Bref, ce que je veux dire c'est que le fonctionnel d'accord mais en réalisant que ce n'est pas gratuit et que les problèmes sont encore là mais sous d'autres formes.
2  0 
Avatar de
https://www.developpez.com
Le 26/07/2010 à 19:06
Programmation parrallèle selon Intel : http://software.intel.com/en-us/parallel/
Pour ceux qui ont du temps devant eux !
Threads are evil : Avoid them ! (D. Richard Hipp sqLite)
The problem with threads (Edward A. Lee Berkeley) :
http://www.eecs.berkeley.edu/Pubs/TechRpts/2006/EECS-2006-1.pdf

Sinon, les telecoms se prêtent très bien au multithread contrairement au reste.
La règle "Un thread = un device (telecom, GPU, sound, ...)" fonctionne pas trop mal.
En traitement de raw input : division du raw par le nombre de core : marche parfois aussi (sauf si agregation) (zip, flat, trt de signal)
SGBD : monothread obligatoire (voir titre).
Le reste est un casse tête à moins de faire "dormir" les threads pour.. imiter le monothread par synchronisation... J'espere que les core48 supporteront le turbo-boost.
C'est un peu ce que pense Bill Dally, un des ingénieurs les plus importants de Nvidia, mais dans un registre différent lorsqu'il écrit dans Forbes « après 40 ans de programmation linéaire [il faudrait] une rupture avec les pratiques de longue date ».
D'accord avec ce qu'il dit, c'est même exactement ce que je dis aussi, sauf que ça ne dit pas qu'on pourra faire en parrallèle ce qu'on fait en séquentiel et personnellement j'en doute. Comme tout le monde l'exige, je ne demande qu'à apprendre mais parfois.. l'info n'est pas là !
Et la solution non plus..

Multicore et multi servers sont des disciplines très voisines pour le traitement. J'ai fait un peu des deux mais peut-être qu'un grand maître du multi-server pourrait donner quelques trucs et astuces....
1  0 
Avatar de
https://www.developpez.com
Le 27/07/2010 à 20:41
Citation Envoyé par S(ô.Ô)B Voir le message

On peut très bien paralléliser un tri rapide : multi-threaded quicksort
Et regardez les gains de performance à la fin !

Je pense que la problématique actuelle pour les "gros" calculs est de repenser les algorithmes derrières afin de tirer parti au mieux des processeurs multi-cores. Mais cela a un véritable coût pour les logiciels car penser parallèle, et non plus itératif, n'est pas une gymnastique intellectuelle auquelle on a été habitué...
Merci encore pour ce lien ! après lecture , je constate que cette page concerne l'hyperthreading d'intel et non pas (encore) le multicore. Le résultat est quand même passionnant et confirme qu'il faudra lire attentivement les publications intel si on veut "accrocher les wagons" quand les processeurs atteindront plusieurs 10zaines ou 100aines de core. C'est un peu dans cette optique que ça devient intéressant. D'ici là , on peut se former et améliorer la portabilité de l'existant vers le massivement parallèle mais...

Il me semble un peu prématuré de se risquer dans cette direction si au moins une copie du logiciel qu'on développe risque de tourner sur Atom N270 !

Pour les traitements GPU c'est différent mais connaissez vous une seule personne qui travaille vraiment sur GPU ? moi aucun , pourtant s'il y avait vraiment un challenge de ce coté, plusieurs collègues ou concurrents auraient produit quelque chose. Or actuellement dans ma spécialité le processeur de l'extrème parallèle est le powerPC !! qui a remplacé les anciens réseaux de DSP dont les systèmes de développement sont restés anecdotiques

La vraie rupture technologique est plutôt dans les prochaines générations de CPU 50 ou 100 cores. Mais je suis quelqu'un de trop concret pour m'avancer à des prévisions sur quelque chose que je n'ai pas les moyens de tester à part un I7 core 4 hyper threading : soit 8 cores virtuels.

Cela dit, jamais la programmation parallèle n'a jamais été aussi imminente et c'est vrai qu'il y a de quoi s'enthousiasmer. Anticiper le marché est un jeu très dangereux sur un plan professionnel mais certainement pas dans les conversations ou l'imagination.

Au point de vue du style de conception , ce ne sera pas une rupture plus traumatique que les précédentes, et il est amusant d'anticiper des architectures à centaines de cores dans un smartphone ce qui devrait arriver assez vite... tandis que les machines traditionnelles pourraient bien en totaliser des millions ou en tout cas , on peut rêver. Encore une fois, l'amérique me cloue au sol et parvient à sauver son modèle de croissance.

Je ne suis pas vraiment enclin à me diriger vers des méthodes comme celles qu'on enseigne à l'école aujourd'hui ou à utiliser le terme paradigme plus d'une fois par an. Peut-être un collègue habile me fera changer d'avis et adopter ce vocabulaire. En l'état et dans mon échelle très personnelle un peu heroïc fantasy , je dirais que c'est une nouvelle forme de vie dont la multiplication cellulaire pourrait bien , un jour , s'inspirer de la nature et croitre par elle même pour former des entités de la taille d'un système stellaire et d'une intelligence bien supérieure à celle de ses concepteurs. Ca m'a ouvert l'appétit

Bonne soirée
1  0 
Avatar de hsyl20
Membre à l'essai https://www.developpez.com
Le 29/07/2010 à 23:57
Bon alors déjà il y a plusieurs objectifs :
- l'application utilise plusieurs processus/threads/etc. à cause de certaines contraintes (thread dédié à l'interface utilisateur, thread en attente sur un socket, etc.) => programmation concurrente
- l'application a besoin d'aller le plus vite possible et pour cela doit utiliser au mieux les différentes unités de calcul présentes => programmation parallèle

Dans le premier cas, le nombre de threads est fixe et dépend de la sémantique. Dans le second cas, le nombre de "threads" peut potentiellement varier en fonction de l'architecture. Dans la suite je ne parle que de programmation parallèle (dont l'objectif est les performances).

1) Inconvénients des programmes impératifs
Quand vous écrivez un programme avec un langage impératif, vous donnez une suite d'ordres (d'où le nom "impératif") qui sont implicitement en séquence :
faireci();
faireça();
Implicitement vous savez que faireça() va être exécuté après faireci(). Parfois c'est ce qu'on veut :
a = 10;
b = a+1;
Parfois c'est une contrainte inutile :
a = 10;
b = 11;
Le gros du boulot du compilateur est de savoir quelles sont les vraies dépendances et quelles sont celles qui ont été introduites pour rien. Vous pouvez aider le compilateur en utilisant certains mots clés (const, restrict, etc.) qui lui donnent des informations supplémentaires. Sachant ça, le compilo peut vectoriser (instructions SSE) plus facilement ou réordonner les instructions sans que la sémantique ne change bien sûr.

Le problème est que le compilo n'a souvent pas assez d'informations pour savoir qu'il peut paralléliser le code. Dans l'exemple ci-dessus, le compilo ne peut pas déterminer si "faireça()" dépend d'effets de bord (modification d'une variables quelque part en mémoire) de "faireci()", il ne parallélisera donc jamais ce code. Pour paralléliser ça, vous pouvez utiliser OpenMP :
#pragma omp parallel num_threads(2)
{
if (omp_get_thread_num() == 0)
faireci();
else
faireça();
}
C'est tout de suite beaucoup plus contraignant... Et encore avec OpenMP, c'est simple. Si vous voulez gérer vos threads à la main avec mutexes, spinlocks, conditions, etc. ça devient encore plus sympa.

1.1) Nombre de threads et placement
Un autre problème est le nombre de threads. Si vous avez N sections potentiellement exécutables en parallèle et P cores, combien de threads créer simultanément ? Si vous créez N threads avec N très grand, vous allez plomber votre OS. La création de thread a un coût. D'ailleurs il est préférable d'utiliser des threads en espace utilisateur schedulés sur des threads usuels. Il faut alors également bien choisir les stratégies d'ordonnancement des sections parallèles sur les différents threads.

Encore un autre problème : le placement des threads. Si deux threads partagent des données, il est préférable qu'ils soient placés sur deux cores qui partagent un cache. Ensuite il faut éviter le "false sharing" (deux threads éloignés qui écrivent dans deux zones mémoires proches telles qu'elles partagent la même ligne de cache). Les coûts peuvent être beaucoup plus élevés dans le cas d'architectures NUMA.

1.2) Parallélisme imbriqué
Si vous avez des sections parallèles imbriquées dans d'autres sections parallèles, les stratégies d'ordonnancement peuvent être modifiées. Les affinités (partage de données) entre sections parallèles peuvent évoluer, etc.

1.3) Conclusion langages impératifs
Ça fait rêver non ? Et encore, on n'a pas parlé des clusters qui exécutent des programmes qui communiquent par le (ou les...) réseau(x) en utilisant MPI.Pour rester simple, je vais parler de la programmation sur GPU.

2) Programmation GPU
On utilise soit CUDA (de NVidia), soit OpenCL. OpenCL étant un standard fortement inspiré de CUDA, je vais parler de ça. À noter qu'AMD/ATI avait aussi sa technologie Stream mais ça n'était pas très répandu. Maintenant qu'AMD et NVIDIA supportent plus ou moins OpenCL, c'est un peu moins la foire.

2.1) OpenCL
Bon alors c'est simple :-) vous avez des fonctions pour transférer des données depuis/vers la mémoire principale du PC (RAM) vers/depuis la mémoire principale de la carte graphique. Les transferts peuvent être synchrones ou asynchrones (DMA...). Le mieux c'est d'anticiper et de les faire en asynchrone le plus tôt possible.

Vous écrivez un "kernel" OpenCL : ça rassemble à une fonction classique, sauf qu'elle va être exécutée en parallèle par N threads (N <= 512 jusqu'à récemment pour les cartes NVIDIA). Vous avez accès au numéro du thread donc vous pouvez faire des traitements spécifiques en fonction du numéro du thread (comme en MPI quoi). Ces threads ont accès à la mémoire principale de la carte graphique. Ils peuvent donc utiliser les données que vous avez préalablement transférées.

Cependant l'accès à cette mémoire et relativement lent. Heureusement il existe une petite mémoire (16KB) à accès rapide dans laquelle les threads peuvent stocker des données. Les threads peuvent se synchroniser (barrières, etc.) et partager des données à travers cette mémoire (ou la mémoire principale). Bon je ne vous raconte pas le "coalescing" en détail, mais en gros si vous voulez que les accès à la mémoire partagée soient encore plus rapides, il faut que les threads accèdent simultanément à des données contigües (le thread n accède à la donnée A[n], le thread n+1 accède à la donnée A[n+1], etc.).

Bon jusque là c'est facile. Sauf qu'en fait des groupes de threads comme ça, on peut en exécuter plusieurs en parallèle. Plus vous avez une carte puissante, plus elle peut exécuter simultanément de groupes de threads. Donc il FAUT en exécuter plusieurs en parallèle pour exploiter la carte. Ces groupes de threads ne peuvent pas communiquer entre eux (pas de barrières, etc.).

2.2) Conclusion GPU
Le modèle de programmation sur GPU est complètement différent. La communication entre la mémoire principale et le GPU doit se gérer comme on gère un réseau (transferts asynchrones, placement des threads de communication avec le GPU sur les coeurs à proximité des bus PCI-E, etc.). On peut aussi avoir plusieurs cartes graphiques, ce qui complexifie encore plus.

3) Les langages fonctionnels
Voyons pourquoi les langages fonctionnels sont de plus en plus courtisés ces derniers temps.

3.1) Fonctions pures et variables immutables
Une fonction pure est une fonction qui ne dépend pas de l'environnement et qui ne le modifie pas. En gros si j'appelle f(a,b,c) à n'importe quel moment dans mon programme, j'obtiendrai le même résultat. C'est une fonction au sens mathématique en fait, donc avec de vraies propriétés.

De la même façon, une variable immutable est en fait une variable au sens mathématique. En maths quand vous posez "a = racine(168)", la valeur de "a" ne va pas changer au cours de votre calcul ("je pose a = 36 et b = f(a). Combien vaut a ?". En C (avec un pointeur) on ne peut même pas répondre à ça dans le cas général).

Donc en fonctionnel quand vous écrivez :
a = f(10)
b = f(a)
Il y a une dépendance entre ces deux lignes. Alors que quand vous écrivez :
a = f(10)
b = f(18)
Vous pouvez être certain (et le compilo aussi) qu'il n'y a pas de dépendance entre ces deux lignes. De plus, si vous avez :
a = f(10)
b = f(10)
Le compilo peut optimiser en :
a = b = f(10)
(cf Common Subexpression Elimination, Memoization, etc.)

Bon alors déjà on voit qu'on n'a pas les contraintes nuisibles des langages impératifs. On a d'autres contraintes, j'en parle après.

3.2) Data Parallelism
Un des gros défaut des langages fonctionnels usuels est qu'ils reposent majoritairement sur des structures récursives (listes) et emploient donc des algorithmes récursifs. Par exemple pour appliquer une fonction à tous les éléments d'une liste, vous allez utiliser la fonction Map définie naïvement comme suit (exemple en Scala) :
def map(maliste: List[A], f: A => B): List[B] = maliste match {
case Nil => Nil
case x :: xs => f(a) :: map(xs, f)
}

On voit bien que la fonction Map s'auto-appelle en séquence pour tous les éléments de la liste. L'idée est donc d'utiliser des structures de données non récursives avec lesquelles on peut travailler en parallèle. En gros, des vecteurs/tableaux.

On trouve ce type de langage chez Intel (Intel Ct) mais ils n'ont rien inventé puisque NESL le faisait il y a 17 ans. Ce type de langage devrait revenir à la mode.

3.3) Défauts de l'approche fonctionelle
Un des gros défaut de l'approche fonctionnelle est que l'on ne modifie pas les données (données immutables). Du coup, si vous voulez changer la valeur d'une cellule d'un tableau, vous devez en faire une copie avec la cellule actualisée à sa nouvelle valeur. Ça devient vite très lent pour des tableaux de millions d'éléments.

Dans certains cas, le compilateur peut détecter que le tableau source ne sera plus utilisé et faire une modification in-place. Dans le cas général, il ne peut pas.

3.4) Conclusion langages fonctionnels
On a vu que l'approche fonctionnelle avec data-parallelism résout de nombreux problèmes et permet au compilo de trouver du parallélisme plus facilement. Cependant les modifications in-place restent nécessaires dans certains cas pour avoir de bonnes perfs. Une solution est l'approche hybride : le programme utilise principalement le paradigme fonctionnel ; certaines fonctions sont écrites en langage impératif mais respectent les contraintes fonctionnelles (pas d'effet de bord).

4) Conclusion
OpenCL (côté hôte, pas dans les kernels) est très proche du paradigme fonctionnel. On exécute des kernels en indiquant les dépendances entre eux et ces kernels sont quasiment purs (buffers ReadWrite exceptés). Ça reste très contraignant et l'exécution de kernels sur CPU ("supporté" par AMD) n'est pas encore terrible. C'est déjà un progrès car ça force les développeurs à isoler des portions parallélisables et quasi-pures de leur code.

La gestion efficace des cartes graphiques et des transferts mémoire est très compliquée. C'est pourquoi certains travaux de recherche visent à fournir une couche au-dessus d'OpenCL/CUDA (voir le runtime StarPU).

Pour conclure, le paradigme fonctionnel sera donc forcément remis au goût du jour, même si ça ne ressemble pas à du Lisp. Les compilos ont besoin de propriétés pour travailler sur les codes. Les codes ne peuvent plus être à la fois portables et tunés à la main car il y a trop de facteurs à prendre en compte : nombre de coeurs, topologies des coeurs, cartes graphiques (capabilities...), mémoire disponible sur chaque carte graphique, NUMA, etc. Autant on pouvait s'en sortir avec des #ifdef bien crades auparavant pour passer de PowerPC à x86 à x86_64, autant ça n'est plus possible maintenant.
1  0 
Avatar de pseudocode
Rédacteur https://www.developpez.com
Le 27/07/2010 à 0:29
Citation Envoyé par Idelways Voir le message
Dans l'ère du multicoeurs, pensez-vous comme Bray que les paradigmes de programmation fonctionnelle et concurrente soit plus adaptés ?
Oui. Mais ce n'est pas pour autant qu'il faut vouloir enterrer la programmation impérative. Remplacer les programmes 100% impératif par des programmes 100% fonctionnel c'est un peu extrème comme approche.

Je préfèrerai que les langages impératif traditionnels évoluent pour intégrer proprement les paradigmes fonctionnels/concurrents. On n'a pas tout le temps besoin de penser en multicoeurs.
0  0 
Avatar de zul
Membre éclairé https://www.developpez.com
Le 27/07/2010 à 8:38
Pour intégrer proprement le fonctionnel, il faut commencer par intégrer le concept de fonction pure (ou transparence référentielle ou autre terme à la mode) qui est en soit assez contradictoire avec impératif.

Je ne vois pas bien où est la simplification. Il dit juste que d'utiliser des paradigmes différents que le sacro-saint objet-impératif pourrait s'avérer judicieux pour gérer les problématiques "multi-//". À mon avis, ça ne se fera justement pas rapidement, parce que c'est compliqué : ce n'est pas juste voir de syntaxe comme entre Java / C# / autre clone objet, mais profondément repensé les paradigmes à utiliser / les architectures qui vont avec.

Erlang en soit n'est pas extrêmement performant sur un seul score, mais il passe bien à l'échelle sur n-core / n-machines (sans compter la gestion des nodes qui tombent etc ...).
0  0 
Avatar de Julien Bodin
Membre éclairé https://www.developpez.com
Le 27/07/2010 à 8:39
Citation Envoyé par oxyde356 Voir le message
Je trouve que cette politique est responsable de l'abaissement du niveau des développeurs comme l'a été le mouvement massif vers Java ... si on continue comme ça on ne va faire plus que des scripts
C'est quoi ce vieux troll ?
0  0 
Avatar de oxyde356
Membre éprouvé https://www.developpez.com
Le 27/07/2010 à 8:42
Citation Envoyé par julien.1486 Voir le message
C'est quoi ce vieux troll ?
Je n'avais aucunement l'intention de pourrir Java, je l'ai pris au hasard
0  0 
Avatar de S(ô.Ô)B
Membre régulier https://www.developpez.com
Le 27/07/2010 à 10:44
Pour avoir déjà fait de l'Erlang, je suis tout à fait d'accord avec amaury pouly, lorsqu'on programme en fonctionnel pur comme Erlang d'autres problèmes apparaissent, et souvent pas des moindres. Mais ce langage est vraiment intéressant et j'invite tout le monde à y jeter un coup d'œil ne serait-ce que pour sa gestion de la modification du code à chaud, ou du parallélisme sur plusieurs machines déconcertant de facilité à mettre en place.

Après par rapport à l'intervention de Tim Bray, qui dit en gros que les threads c'est le mal car les données sont partagées, et ben avec un peu de discipline et de rigueur de programmation on peut très bien travailler qu'avec des données propres à chaque thread...
0  0 
Avatar de
https://www.developpez.com
Le 27/07/2010 à 11:12
Citation Envoyé par amaury pouly Voir le message
Je dois voir le mal partout mais en quoi cet article est-il pertinent ? En gros il dit "les threads c'est mal" parce que c'est non-déterministe. Il dit aussi que le non-déterminisme c'est mal. Or certaines tâches sont non-déterministes. Si le code a une partie GUI et une partie calcul, une intervention de l'utilisateur est une action non-déterministe.

Je pense qu'on peut tourner le problème comme on veut, faire du message passing, faire des diagrammes et tout ce qu'on veut mais le problème fondamental c'est de faire plusieurs choses à la fois et cela nécessitera toujours de la synchronisation et donc il y aura un risque de bug.

On parle aussi beaucoup de la programmation fonctionnelle pour le calcul en parallèle et c'est vrai que c'est tentant étant donné que toutes les structures de données sont en lecture seulement. Toutefois, cela cache aussi ses propres problèmes. Par exemple, en fonctionnelle, tout est en lecture mais comme on écrit ? En créant des objets ! Or créer des objets demande de la mémoire qu'il faut allouer et libérer. Donc le problème n'a pas disparu.
Par ailleurs, on peut aussi perdre en performance puisque l'idée de la plupart des structures de données fonctionnelle c'est qu'on a l'intégralité de l'historique des modifications. En pratique cela veut dire que si on une structure A et qu'on veut la modifier pour obtenir B alors on représente B par représente A + modification. Autrement dit on se retrouve avec un empilement de modifications qui si elles ne sont pas bien faites seront moins performantes.
Bref, ce que je veux dire c'est que le fonctionnel d'accord mais en réalisant que ce n'est pas gratuit et que les problèmes sont encore là mais sous d'autres formes.
Parlez vous de l'article développez ?
De la blague de R.Hipp ? j'aime bien ce gars car il a eu du succès , n'appartient à aucune grosse compagnie et a une vision très scandinave du monde, donc il parle comme ça lui vient et dit bien haut ce que tout le monde murmure ...

Les questions de thread ne datent pas du premier multicore , cela existe depuis Unix. Or s'il est vrai que des virtuoses ont posé les jalons d'un certain multithreading , il s'agit le plus souvent de software réseau-telecom. Cela concerne un petit nombre de développeurs. Un exemple parlant est l'usage que FTP fait des caractères jokers.

Pour le reste, dans le meilleur des cas , on a des synchros encombrantes en code comme en cpu. Dans les cas plus tordus, on modifie la structure du programme pour gérer des evènements soit existants dans le framework soit réécrit à la main (boucles infinies ...) C'est de cette manière qu'on peut quand même faire de la BDD asynchrone (multithread donc) même si M Hipp ne nous le conseille pas. En effet, il ne suffit pas d'orchestrer une messagerie interne : on a aussi des problèmes d'accès concurrent qu'on gère en interne avec des delegates mais ça ne suffit pas non plus et notamment dans le cas de R.Hipp et son sqlite qui n'est pas très multi-users mais c'est juste un cas parmi d'autres.

Donc le deal est : désormais le multithread n'est plus une amélioration des techniques existantes mais une nécessité rendue obligatoire par l'industrie des processeurs qui n'arrive plus à monter en fréquence (je résume beaucoup)

Avant que nos élites nous demandent de tout refaire en multithread , je crois urgent de dire que le multithread n'est pas une bonne solution sauf pour les telecom+++ et dans une moindre mesure quelques problèmes pas trop itératifs(GPU?..). Mais que pour un très grand nombre de cas, ils n'apportent absolument rien , si ce n'est un paquet d'ennuis avec du software qui marchait très bien en monothread..

Plus proche de l'utilisateur on peut designer du fonctionnel astucieux et très spécifique pour lui rendre la vie plus agréable, mais pour conclure je dirais surtout :

Le software ne peut pas gagner avec le multithread autant que le hardware actuellement. Un processeur à 48 coeurs ne sera jamais 48x plus rapide mais il pourra faire le travail de 48 machines auparavant .. Peut-être avez vous des idées de formulation plus diplomatique (je suis preneur)
0  0