Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Multithreading

21 réponses
Avatar
ALB
Bonjour =E0 tous,

je n'ai jamais fait de multithreading et je cherche une r=E9f=E9rence
(anglais ou fran=E7ais) pour apprendre, qui remplirait notamment les
crit=E8res suivants :
- indique les design patterns qui passent bien (et ceux =E0 =E9viter), les
bonnes pratiques...,
- non sp=E9cifique =E0 une plateforme.

Adrien

10 réponses

1 2 3
Avatar
jalina
Bonjour à tous,

je n'ai jamais fait de multithreading et je cherche une référence
(anglais ou français) pour apprendre, qui remplirait notamment les
critères suivants :
- indique les design patterns qui passent bien (et ceux à éviter), les
bonnes pratiques...,
- non spécifique à une plateforme.

Adrien


http://www.google.fr/search?q=multithreading

Avatar
Fabien LE LEZ
On Thu, 17 Jan 2008 06:27:24 -0800 (PST), ALB :

je n'ai jamais fait de multithreading et je cherche une référence
(anglais ou français) pour apprendre, qui remplirait notamment les
critères suivants :


"Programming with POSIX threads", David R. Butenhof.
http://www.amazon.fr/P/dp/0201633922/

Il parle des threads POSIX en langage C, mais les principes de
fonctionnement sont les mêmes sous Windows et en C++.

Cf aussi Boost.

Avatar
James Kanze
On Jan 18, 1:55 am, Fabien LE LEZ wrote:
On Thu, 17 Jan 2008 06:27:24 -0800 (PST), ALB :

je n'ai jamais fait de multithreading et je cherche une référence
(anglais ou français) pour apprendre, qui remplirait notamment les
critères suivants :


"Programming with POSIX threads", David R. Butenhof.http://www.amazon.fr/P /dp/0201633922/

Il parle des threads POSIX en langage C, mais les principes de
fonctionnement sont les mêmes sous Windows et en C++.


Oui et non. En effet, c'est un livre excellent pour les threads,
et comme tu dis, beaucoup des principes sont pareils en Windows.
(Encore que... Windows n'a pas de « condition », ou ne l'avait
pas pendant longtemps.) Reste qu'il se positionne à un niveau
assez bas (mais qu'il faut comprendre), et ne s'adresse pas à
des questions plus élevées, du genre des modèles de conception à
utiliser en C++. Il y a effectivement un trou entre lui et des
livres de conception C++, et je ne connais rien qui s'y
position. Un livre, par exemple, qui expliquerait les
différentes façons d'organiser les threads en classes. (J'en
connais trois ou quatre, dont la plus répandue est à mon avis à
éviter.) Ni des modèles de communication entre les threads --
comment implémenter un queue de messages, par exemple. (Dans mon
cas, par exemple, j'ai choisi d'utiser auto_ptr au niveau de
l'interface -- une fois l'objet passé à l'autre thread, le
thread émitteur n'en a plus accès.) Et comment effectuer un
arrêt propre ?

Boost a l'avantage d'offrir une interface portable au primitifs
du threading (et de simuler les condition sous Windows), mais là
aussi, son concept de « thread » est de vraiment bas niveau,
et assez délicat à l'utilisation. Il vaut mieux donc le wrapper
avec quelque chose qui implémente une abstraction plus élevée.

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
Luc Hermitte
Bonjour,

On 18 jan, 09:29, James Kanze wrote:
[...] et ne s'adresse pas à
des questions plus élevées, du genre des modèles de conception à
utiliser en C++. Il y a effectivement un trou entre lui et des
livres de conception C++, et je ne connais rien qui s'y
position.


Dans une certaine mesure, il y a les bouquins et articles de Schmidt,
non? Ils sont très orientés patterns avec pour exemple
d'implémentation sa bibliothèque, ACE -- dont je te sais peu
partisant.

Un livre, par exemple, qui expliquerait les
différentes façons d'organiser les threads en classes. (J'en
connais trois ou quatre, dont la plus répandue est à mon avis à
éviter.)


Ta parenthèse m'interresse. Tu pourrais développer STP (un lien ou un
nom m'irait).

Ni des modèles de communication entre les threads --
comment implémenter un queue de messages, par exemple. (Dans mon
cas, par exemple, j'ai choisi d'utiser auto_ptr au niveau de
l'interface -- une fois l'objet passé à l'autre thread, le
thread émitteur n'en a plus accès.)


Mais, cela ne résout pas le cas où il faut passer le message à
plusieurs threads.

--
Luc Hermitte

Avatar
Michel Decima
Hello,

On 18 jan, 09:29, James Kanze wrote:
[...] et ne s'adresse pas à
des questions plus élevées, du genre des modèles de conception à
utiliser en C++. Il y a effectivement un trou entre lui et des
livres de conception C++, et je ne connais rien qui s'y
position.


Dans une certaine mesure, il y a les bouquins et articles de Schmidt,
non? Ils sont très orientés patterns avec pour exemple
d'implémentation sa bibliothèque, ACE -- dont je te sais peu
partisant.


J'allais aussi citer Schmidt, mais tu as dégainé le premier.


Un livre, par exemple, qui expliquerait les
différentes façons d'organiser les threads en classes. (J'en
connais trois ou quatre, dont la plus répandue est à mon avis à
éviter.)


Ta parenthèse m'interresse. Tu pourrais développer STP (un lien ou un
nom m'irait).


Ca m'interesse aussi. Je connais au moins une facon de faire (celle
de Boost), mais je ne sais pas si c'est la plus répandue... Bref, si
tu pouvais nous donner quelques indications, je suis preneur, merci
d'avance.

Ni des modèles de communication entre les threads --
comment implémenter un queue de messages, par exemple. (Dans mon
cas, par exemple, j'ai choisi d'utiser auto_ptr au niveau de
l'interface -- une fois l'objet passé à l'autre thread, le
thread émitteur n'en a plus accès.)


Mais, cela ne résout pas le cas où il faut passer le message à
plusieurs threads.


Dans ce dernier cas, est ce qu'on peut vraiment eviter d'avoir
une queue par thread, et donc il faudra bien dupliquer le message
a un moment ou un autre ?


Avatar
Sylvain
Michel Decima wrote on 21/01/2008 13:52:

Mais, cela ne résout pas le cas où il faut passer le message à
plusieurs threads.


Dans ce dernier cas, est ce qu'on peut vraiment eviter d'avoir
une queue par thread, et donc il faudra bien dupliquer le message
a un moment ou un autre ?


cela peux dépendre de la "durée de vie" des messages.
e.g. on peux imaginer un cas où un msg devient inutile (par trop
obsolète) et peux être purgé d'une unique queue où tous seraient empilés
(remarque même dans ce cas je préfèrerais que les threads reçoivent une
copie du msg, la queue peux néanmois être globale).

Sylvain.


Avatar
James Kanze
On Jan 21, 11:16 am, Luc Hermitte wrote:
On 18 jan, 09:29, James Kanze wrote:

[...] et ne s'adresse pas à
des questions plus élevées, du genre des modèles de conception à
utiliser en C++. Il y a effectivement un trou entre lui et des
livres de conception C++, et je ne connais rien qui s'y
position.


Dans une certaine mesure, il y a les bouquins et articles de Schmidt,
non? Ils sont très orientés patterns avec pour exemple
d'implémentation sa bibliothèque, ACE -- dont je te sais peu
partisant.


Je sais qu'il en a écrit. Je ne sais pas trop ce qu'ils
valent ; quand j'ai essayé d'utiliser ACE, j'en étais très
deçu, aussi bien côté qualité que côté utilisabilité.

En général, de toute façon, je me pose la question d'actualité.
On a appris beaucoup sur les threads depuis peu, et Schmidt me
semble rester sur l'ancien modèle, un peu comme le
java.lang.Thread dans Java. À choisir, je préfère encore le
modèle Boost.

Un livre, par exemple, qui expliquerait les
différentes façons d'organiser les threads en classes. (J'en
connais trois ou quatre, dont la plus répandue est à mon avis à
éviter.)


Ta parenthèse m'interresse. Tu pourrais développer STP (un lien ou un
nom m'irait).


Malheureusement, ce sont des choses que j'ai appris par ci, par
là, sans vraiment savoir où. Un modèle, c'est évident : c'est
celui de ACE, qui est aussi plus ou moins celui de Java -- 'est
grosso mode l'utilisation du modèle du méthode template pour la
class Thread, avec customisation par dérivation pour la fonction
à exécuter dans le thread. C-à-d state of the art il y a quinze
ans, mais avec des problèmes bien connus entre temps. (Java
l'étend en offrant l'option entre le modèle du méthode template
et le modèle stratégie, avec customisation par un délégué. Entre
temps, il est fortement conseillé d'utiliser le délégué.)

Boost va à l'autre extrème : la fonction du thread est un objet
fonctionnel, qui se fait copier, et le thread lui-même tourne
sur une copie. Ce qui évite les problèmes du modèle template, et
quelques autres aussi, mais rend plus difficile la communication
entre le thread parent et le thread fils, surtout en cas de
join.

Il y a aussi un modèle avec des « futures » -- je ne le
connais pas trop bien, mais il y a eu des suggestions de
certains qu'on devait le considérer pour la normalisation.
Grosso modo, si j'ai bien compris, l'interface est celui d'une
fonction (ou peut-être plutôt d'une fonction qui prend un objet
fonctionnel avec la véritable fonction), avec une valeur de
retour qui est un espèce de proxie, qui permet à récupérer la
valeur de retour de l'objet fonctionnel plus tard. Je n'ai pas
assez d'expérience pour réelement juger, mais a priori, il doit
être intéressant dans certains cas des threads joiné, au moins.

Dans mes propres utilisations, je distinque assez nettement
entre les threads détachés et ceux joignables : les threads
détachés sont lancés par une fonction (et ne correspondent pas
un un objet -- il n'y a pas de classe), mais dans l'ensemble,
l'implémentation n'est pas loin de celle de Boost. Les threads
joignable, en revanche, c'est bien une classe, dont appeler le
destructeur avant le join est une erreur grave (échec
d'assertion). Mais les deux ont été conçus en fonction des
besoins spécifiques, et sont loins de couvrir tous les besoins.
(Je suis convaincu qu'il faut bien distinguer entre les threads
détachés et les threads joignables dès la création du thread. Et
je crois que j'ai trouvé à peu près le bon modèle pour les
threads détachés. En revanche, je sais qu'il y a des cas
d'utilisation des threads joignables qui sont mal couverts par
le modèle que j'utilise.)

Ni des modèles de communication entre les threads --
comment implémenter un queue de messages, par exemple. (Dans mon
cas, par exemple, j'ai choisi d'utiser auto_ptr au niveau de
l'interface -- une fois l'objet passé à l'autre thread, le
thread émitteur n'en a plus accès.)


Mais, cela ne résout pas le cas où il faut passer le message à
plusieurs threads.


Dans quel sens ?

-- S'il s'agit de passer le message du thread A à thread B, et
ensuite, thread B le passe à thread C, et ainsi de suite, il
n'y a pas de problème.

-- De même s'il s'agit de passer le message à un pool de
threads, ou chaque message n'est effectivement reçu que d'un
seul thread, même s'il y a plusieurs candidats.

-- En revanche, il n'est pas conçu pour une emission
« broadcast ». Chose dont je n'avais pas besoin, mais qui
pourrait sans doute être utile dans d'autres applications.
(A priori, dans de tels cas, je préfèrerais un passage par
copie, de façon à ce que chaque thread ait sa propre copie
privée du message.)

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
Loïc Joly

Dans mes propres utilisations, je distinque assez nettement
entre les threads détachés et ceux joignables : les threads
détachés sont lancés par une fonction (et ne correspondent pas
un un objet -- il n'y a pas de classe), mais dans l'ensemble,
l'implémentation n'est pas loin de celle de Boost. Les threads
joignable, en revanche, c'est bien une classe, dont appeler le
destructeur avant le join est une erreur grave (échec
d'assertion).


J'ai pour ma part tendance à distinguer entre deux catégories d'usage
multithread :
- Les threads pour aller plus vite,
- Les threads pour faire plus de choses en même temps.

Typiquement les threads pour aller plus vite, qui dépendent d'une
architecture multi-coeurs, me semble bien modélisés par les futures (que
je n'ai pas encore eu l'occasion d'utiliser), des boucles qui s'auto
parallèlisent, voir des appels de fonction dont on ne sait même pas
s'ils sont multithread ou pas.

Les threads pour faire plus en même temps me semblent déjà bien plus
structurant au niveau du programme, font souvent tourner une boucle dans
leur fonction principale, avec ou sans timer,...

Je me demande dans quelle mesure cette classification est compatible
avec la classification joignable/détaché que tu proposes.

--
Loïc

Avatar
James Kanze
On Jan 21, 7:56 pm, Loïc Joly
wrote:

Dans mes propres utilisations, je distinque assez nettement
entre les threads détachés et ceux joignables : les threads
détachés sont lancés par une fonction (et ne correspondent pas
un un objet -- il n'y a pas de classe), mais dans l'ensemble,
l'implémentation n'est pas loin de celle de Boost. Les threads
joignable, en revanche, c'est bien une classe, dont appeler le
destructeur avant le join est une erreur grave (échec
d'assertion).


J'ai pour ma part tendance à distinguer entre deux catégories d'usage
multithread :
- Les threads pour aller plus vite,


Sur un processeur multi-CPU. Sinon, ils rallentissent.

- Les threads pour faire plus de choses en même temps.


Est-ce que tu veux dire : pour pouvoir interrompre une activité
pour en traiter quelque chose de plus importante ? Genre,
remettre à jour la graphique, bien qu'il y ait un calcul
important qui n'a pas fini.

Typiquement les threads pour aller plus vite, qui dépendent
d'une architecture multi-coeurs, me semble bien modélisés par
les futures (que je n'ai pas encore eu l'occasion d'utiliser),


Je ne suis pas trop sûr (mais il me manque réelement de
l'expérience récente -- la dernière fois que j'ai eu à faire des
exécutions en parallel pour gagner la vitesse, c'était en 1979).
Le problème, en général, c'est que tu as plusieurs threads, non
seulement deux, et qu'il faut attendre que tous soient finis
avant de continuer (alors que très souvent, au moins dans les
cas que j'ai connu, les « resultats » se trouvaient bien dans un
tableau en mémoire).

des boucles qui s'auto parallèlisent, voir des appels de
fonction dont on ne sait même pas s'ils sont multithread ou
pas.


Les boucles qui s'auto-parallèlisent, c'est difficile avec la
sémantique des pointeurs à la C:-). En revanche, déjà dans les
années 1980, on le faisait en Fortran (qui n'était pas sans
problèmes non plus).

Mais si la boucle s'auto-parallèlise, on n'a pas besoin d'un
modèle de thread visible à l'utilisateur. Pour l'utilisateur,
c'est toujours du mono-thread ; c'est le compilateur qui
s'occupe du reste. (Ou est-ce que je prends mes désirs pour la
réalité. Je sais que dans les années 1980, il y avait un Kennedy
qui faisait des recherches assez intéressantes sur la
parallèlisation automatique à l'université Rice, aux USA.)

Les threads pour faire plus en même temps me semblent déjà bien plus
structurant au niveau du programme, font souvent tourner une boucle dans
leur fonction principale, avec ou sans timer,...


Je ne suis pas sûr que je comprends.

Je me demande dans quelle mesure cette classification est compatible
avec la classification joignable/détaché que tu proposes.


C'est une classification dérivée de l'API que j'utilise, je
l'avoue. Le thread détaché, en tant que tel, a bien une
existance plus abstrait, dans la gestion des GUI, par exemple
(où il rend son « résultat » en générant un évenemment dans le
thread de gestion de la GUI -- évenement qui provoque
l'affichage de son résultat). Quant aux threads « joignables »,
j'avoue que ça couvre beaucoup. Dans mon cas, je n'en avais
qu'un, et donc, un modèle suffisait. Mais je doute que c'est le
cas général.

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
Loïc Joly

- Les threads pour faire plus de choses en même temps.



Est-ce que tu veux dire : pour pouvoir interrompre une activité
pour en traiter quelque chose de plus importante ? Genre,
remettre à jour la graphique, bien qu'il y ait un calcul
important qui n'a pas fini.


Oui. Dit autrement, des threads pour la réactivité, plus que pour les
performances.



Les threads pour faire plus en même temps me semblent déjà bien plus
structurant au niveau du programme, font souvent tourner une boucle dans
leur fonction principale, avec ou sans timer,...


Je ne suis pas sûr que je comprends.


Je voulais dire par là que souvent, ce genre de thread a une durée de
vie (et des responsabilités) plus grande que cette d'un thread pour les
performances. Et ces threads n'ont pas un début et une fin intrinsèques,
mais tournent en boucle jusqu'à ce qu'on leur demande d'arrêter.

Et dans certains domaines, liés au temps réel entre autre, certains de
ces threads ont une durée de vie égale à celle du programme, et des
contraites en qualité de cadencement qui leur sont propres.

Il est pour moi assez différent de dire que le calcul sera dans un
thread à part pour que l'affichage continue à se raffraichir (et les
contraintes de qualité s'exprimeront le plus souvent en temps maximum
avant le réveil du thread), et que dire que la mise en forme et l'envoi
d'information à tel actionneur s'effectuera dans un thread à part,
cadencé à 30ms +/- 1ms.

Cette notion de thread cadencée, aujourd'hui, je l'effectue en ayant
simplement un thread qui boucle avec une attente sur un timer, mais je
me demande si c'est vraiment le bon modèle.

Dans les deux cas, le réveil du thread s'effectue par un évènement
(mouvement souris ou timer), mais il y a suffisemment de différences
entre les deux cas pour que je veuille les séparer (par exemple la
gestion de ce qui se passe quand l'évènement est réémis alors que le
traitement précédent n'a pas eu le temps de se terminer).

Finalement, j'en arrive à la classification suivante :

- Thread pour la performance
- Thread pour la réactivité
- Cadencé
- Réveillé par des évènements autres


--
Loïc



1 2 3