"J-F Portala" a écrit dans le message de news:
4851193d$0$19724$Merci de vos reponses.
Tu évoquais le fait qu'un compilateur récent effectuerait la tâche tout
seul.
Cela n'a pas l'air d'être simple à vérifier.
J'ai passé un peu de temps sur le net pour avoir des informations sur les
compilateurs et leur capacité
à gérer plusieurs processeurs, mais sans succès.
Est ce que faire du multithreading veut dire automatiquement que les
threads seront affectés aux différents processeurs.
Est ce que cela dépend du compilateur (je travaille avec VC++6.0 plus trés
jeune), ou de l'OS.
Merci
Jeff
Je travaille avec le compilateur d'intel et il y a effectivement une option
d'optimisation qui permet de paraleliser le code automatiquement. Pour mon
cas il y a une légère amélioration, mais il faut noter que j'utilise aussi
plusieurs thread, donc je ne m'attendais pas à des gains spectaculaires.
La meilleur options pour des performances optimales serait probablement
d'utiliser "Intel® Threading Building Blocks". Je n'ai jamais utilisé mais
comme ils disent dans leur publicité: "Thread like an expert whitout being
one!". Ce qui est bien avec cet outil c'est qu'il s'adapte automatiquement
au nombre de coeur présent sur la machine.
--------------
Eric Pruneau
"J-F Portala" <jfportala@free.fr> a écrit dans le message de news:
4851193d$0$19724$426a74cc@news.free.fr...
Merci de vos reponses.
Tu évoquais le fait qu'un compilateur récent effectuerait la tâche tout
seul.
Cela n'a pas l'air d'être simple à vérifier.
J'ai passé un peu de temps sur le net pour avoir des informations sur les
compilateurs et leur capacité
à gérer plusieurs processeurs, mais sans succès.
Est ce que faire du multithreading veut dire automatiquement que les
threads seront affectés aux différents processeurs.
Est ce que cela dépend du compilateur (je travaille avec VC++6.0 plus trés
jeune), ou de l'OS.
Merci
Jeff
Je travaille avec le compilateur d'intel et il y a effectivement une option
d'optimisation qui permet de paraleliser le code automatiquement. Pour mon
cas il y a une légère amélioration, mais il faut noter que j'utilise aussi
plusieurs thread, donc je ne m'attendais pas à des gains spectaculaires.
La meilleur options pour des performances optimales serait probablement
d'utiliser "Intel® Threading Building Blocks". Je n'ai jamais utilisé mais
comme ils disent dans leur publicité: "Thread like an expert whitout being
one!". Ce qui est bien avec cet outil c'est qu'il s'adapte automatiquement
au nombre de coeur présent sur la machine.
--------------
Eric Pruneau
"J-F Portala" a écrit dans le message de news:
4851193d$0$19724$Merci de vos reponses.
Tu évoquais le fait qu'un compilateur récent effectuerait la tâche tout
seul.
Cela n'a pas l'air d'être simple à vérifier.
J'ai passé un peu de temps sur le net pour avoir des informations sur les
compilateurs et leur capacité
à gérer plusieurs processeurs, mais sans succès.
Est ce que faire du multithreading veut dire automatiquement que les
threads seront affectés aux différents processeurs.
Est ce que cela dépend du compilateur (je travaille avec VC++6.0 plus trés
jeune), ou de l'OS.
Merci
Jeff
Je travaille avec le compilateur d'intel et il y a effectivement une option
d'optimisation qui permet de paraleliser le code automatiquement. Pour mon
cas il y a une légère amélioration, mais il faut noter que j'utilise aussi
plusieurs thread, donc je ne m'attendais pas à des gains spectaculaires.
La meilleur options pour des performances optimales serait probablement
d'utiliser "Intel® Threading Building Blocks". Je n'ai jamais utilisé mais
comme ils disent dans leur publicité: "Thread like an expert whitout being
one!". Ce qui est bien avec cet outil c'est qu'il s'adapte automatiquement
au nombre de coeur présent sur la machine.
--------------
Eric Pruneau
[...]
En réalité, tu prends un peu le problème à l'envers. Tu as un belle
machine que tu exploites (ou que tu crois exploiter) de manière
insuffisante et cela est frustrant. Le parallélisme de ton application
sera d'autant meilleur que l'application aura été pensée dans ce sens à
l'origine. Cela signifie qu'au lieu de chercher à améliorer le
parallélisme d'un algorithme séquentiel, il est parfois plus productif
de le remplacer par un algorithme intrinsèquement parallèle.
[...]
En réalité, tu prends un peu le problème à l'envers. Tu as un belle
machine que tu exploites (ou que tu crois exploiter) de manière
insuffisante et cela est frustrant. Le parallélisme de ton application
sera d'autant meilleur que l'application aura été pensée dans ce sens à
l'origine. Cela signifie qu'au lieu de chercher à améliorer le
parallélisme d'un algorithme séquentiel, il est parfois plus productif
de le remplacer par un algorithme intrinsèquement parallèle.
[...]
En réalité, tu prends un peu le problème à l'envers. Tu as un belle
machine que tu exploites (ou que tu crois exploiter) de manière
insuffisante et cela est frustrant. Le parallélisme de ton application
sera d'autant meilleur que l'application aura été pensée dans ce sens à
l'origine. Cela signifie qu'au lieu de chercher à améliorer le
parallélisme d'un algorithme séquentiel, il est parfois plus productif
de le remplacer par un algorithme intrinsèquement parallèle.
Eric Pruneau a écrit :
> "J-F Portala" a écrit dans le message de news:
> 4851193d$0$19724$
>> Tu évoquais le fait qu'un compilateur récent effectuerait
>> la tâche tout seul. Cela n'a pas l'air d'être simple à
>> vérifier. J'ai passé un peu de temps sur le net pour avoir
>> des informations sur les compilateurs et leur capacité à
>> gérer plusieurs processeurs, mais sans succès. Est ce que
>> faire du multithreading veut dire automatiquement que les
>> threads seront affectés aux différents processeurs. Est ce
>> que cela dépend du compilateur (je travaille avec VC++6.0
>> plus trés jeune), ou de l'OS.
> Je travaille avec le compilateur d'intel et il y a
> effectivement une option d'optimisation qui permet de
> paraleliser le code automatiquement. Pour mon cas il y a une
> légère amélioration, mais il faut noter que j'utilise aussi
> plusieurs thread, donc je ne m'attendais pas à des gains
> spectaculaires.
> La meilleur options pour des performances optimales serait
> probablement d'utiliser "Intel® Threading Building Blocks".
> Je n'ai jamais utilisé mais comme ils disent dans leur
> publicité: "Thread like an expert whitout being one!". Ce
> qui est bien avec cet outil c'est qu'il s'adapte
> automatiquement au nombre de coeur présent sur la machine.
Je pense que tu peux oublier tout rêve de compilateur
parallélisant. L'analyse d'un code pour en extraire un
parallélisme efficace est extrèmement complexe et ne
fonctionne en pratique que sur des boucles très simples avec
des données (notamment des tableaux) que le compilateur peut
aisément décomposer pour faire naître du parallélisme.
Concrètement, cela signifie qu'en dehors de boucles du type
SAXPY (S = A*X + Y) avec un pas d'accès (stride) regulier
(idéalement 1), où les tableaux (S, A, X et Y) sont non
recouvrants et vus comme tels par le compilateur, le
compilateur choisit la solution de prudence et laisse tout
séquentiel.
Le moindre pointeur dans ta boucle empêche le compilateur de
savoir quelle est la donnée qu'il manipule et si deux
pointeurs sont utilisés, il ne peut pas savoir s'ils ne
pointent pas effectivement sur la même donnée. Les références
constantes améliorent un peu les choses. Très peu.
L'autre problème qui se pose alors est le volume de calcul
nécessaire (grainsize) pour que le parallélisme puisse être
efficace. Si ta boucle est trop petite (=pas beaucoup
d'instructions), tu seras peut-être parallèle, mais au final
tu ne gagneras rien voire tu perdas du temps à créer tes
threads et à les synchroniser.
Eric Pruneau a écrit :
> "J-F Portala" <jfport...@free.fr> a écrit dans le message de news:
> 4851193d$0$19724$426a7...@news.free.fr...
>> Tu évoquais le fait qu'un compilateur récent effectuerait
>> la tâche tout seul. Cela n'a pas l'air d'être simple à
>> vérifier. J'ai passé un peu de temps sur le net pour avoir
>> des informations sur les compilateurs et leur capacité à
>> gérer plusieurs processeurs, mais sans succès. Est ce que
>> faire du multithreading veut dire automatiquement que les
>> threads seront affectés aux différents processeurs. Est ce
>> que cela dépend du compilateur (je travaille avec VC++6.0
>> plus trés jeune), ou de l'OS.
> Je travaille avec le compilateur d'intel et il y a
> effectivement une option d'optimisation qui permet de
> paraleliser le code automatiquement. Pour mon cas il y a une
> légère amélioration, mais il faut noter que j'utilise aussi
> plusieurs thread, donc je ne m'attendais pas à des gains
> spectaculaires.
> La meilleur options pour des performances optimales serait
> probablement d'utiliser "Intel® Threading Building Blocks".
> Je n'ai jamais utilisé mais comme ils disent dans leur
> publicité: "Thread like an expert whitout being one!". Ce
> qui est bien avec cet outil c'est qu'il s'adapte
> automatiquement au nombre de coeur présent sur la machine.
Je pense que tu peux oublier tout rêve de compilateur
parallélisant. L'analyse d'un code pour en extraire un
parallélisme efficace est extrèmement complexe et ne
fonctionne en pratique que sur des boucles très simples avec
des données (notamment des tableaux) que le compilateur peut
aisément décomposer pour faire naître du parallélisme.
Concrètement, cela signifie qu'en dehors de boucles du type
SAXPY (S = A*X + Y) avec un pas d'accès (stride) regulier
(idéalement 1), où les tableaux (S, A, X et Y) sont non
recouvrants et vus comme tels par le compilateur, le
compilateur choisit la solution de prudence et laisse tout
séquentiel.
Le moindre pointeur dans ta boucle empêche le compilateur de
savoir quelle est la donnée qu'il manipule et si deux
pointeurs sont utilisés, il ne peut pas savoir s'ils ne
pointent pas effectivement sur la même donnée. Les références
constantes améliorent un peu les choses. Très peu.
L'autre problème qui se pose alors est le volume de calcul
nécessaire (grainsize) pour que le parallélisme puisse être
efficace. Si ta boucle est trop petite (=pas beaucoup
d'instructions), tu seras peut-être parallèle, mais au final
tu ne gagneras rien voire tu perdas du temps à créer tes
threads et à les synchroniser.
Eric Pruneau a écrit :
> "J-F Portala" a écrit dans le message de news:
> 4851193d$0$19724$
>> Tu évoquais le fait qu'un compilateur récent effectuerait
>> la tâche tout seul. Cela n'a pas l'air d'être simple à
>> vérifier. J'ai passé un peu de temps sur le net pour avoir
>> des informations sur les compilateurs et leur capacité à
>> gérer plusieurs processeurs, mais sans succès. Est ce que
>> faire du multithreading veut dire automatiquement que les
>> threads seront affectés aux différents processeurs. Est ce
>> que cela dépend du compilateur (je travaille avec VC++6.0
>> plus trés jeune), ou de l'OS.
> Je travaille avec le compilateur d'intel et il y a
> effectivement une option d'optimisation qui permet de
> paraleliser le code automatiquement. Pour mon cas il y a une
> légère amélioration, mais il faut noter que j'utilise aussi
> plusieurs thread, donc je ne m'attendais pas à des gains
> spectaculaires.
> La meilleur options pour des performances optimales serait
> probablement d'utiliser "Intel® Threading Building Blocks".
> Je n'ai jamais utilisé mais comme ils disent dans leur
> publicité: "Thread like an expert whitout being one!". Ce
> qui est bien avec cet outil c'est qu'il s'adapte
> automatiquement au nombre de coeur présent sur la machine.
Je pense que tu peux oublier tout rêve de compilateur
parallélisant. L'analyse d'un code pour en extraire un
parallélisme efficace est extrèmement complexe et ne
fonctionne en pratique que sur des boucles très simples avec
des données (notamment des tableaux) que le compilateur peut
aisément décomposer pour faire naître du parallélisme.
Concrètement, cela signifie qu'en dehors de boucles du type
SAXPY (S = A*X + Y) avec un pas d'accès (stride) regulier
(idéalement 1), où les tableaux (S, A, X et Y) sont non
recouvrants et vus comme tels par le compilateur, le
compilateur choisit la solution de prudence et laisse tout
séquentiel.
Le moindre pointeur dans ta boucle empêche le compilateur de
savoir quelle est la donnée qu'il manipule et si deux
pointeurs sont utilisés, il ne peut pas savoir s'ils ne
pointent pas effectivement sur la même donnée. Les références
constantes améliorent un peu les choses. Très peu.
L'autre problème qui se pose alors est le volume de calcul
nécessaire (grainsize) pour que le parallélisme puisse être
efficace. Si ta boucle est trop petite (=pas beaucoup
d'instructions), tu seras peut-être parallèle, mais au final
tu ne gagneras rien voire tu perdas du temps à créer tes
threads et à les synchroniser.
Et voilà le problème dans le C et le C++. Le fait que les
tableaux deviennent très vite des pointeurs, et que le
compilateur ne peut paralleliser que s'il peut établir que les
tableaux (designés par des pointeurs) ne se recouvrent pas.
Et voilà le problème dans le C et le C++. Le fait que les
tableaux deviennent très vite des pointeurs, et que le
compilateur ne peut paralleliser que s'il peut établir que les
tableaux (designés par des pointeurs) ne se recouvrent pas.
Et voilà le problème dans le C et le C++. Le fait que les
tableaux deviennent très vite des pointeurs, et que le
compilateur ne peut paralleliser que s'il peut établir que les
tableaux (designés par des pointeurs) ne se recouvrent pas.
On Jun 18, 10:32 pm, Ivan Dutka-Malen wrote:Je pense que tu peux oublier tout rêve de compilateur
parallélisant. L'analyse d'un code pour en extraire un
parallélisme efficace est extrèmement complexe et ne
fonctionne en pratique que sur des boucles très simples avec
des données (notamment des tableaux) que le compilateur peut
aisément décomposer pour faire naître du parallélisme.
Concrètement, cela signifie qu'en dehors de boucles du type
SAXPY (S = A*X + Y) avec un pas d'accès (stride) regulier
(idéalement 1), où les tableaux (S, A, X et Y) sont non
recouvrants et vus comme tels par le compilateur, le
compilateur choisit la solution de prudence et laisse tout
séquentiel.
Dans la calcule numérique, il paraît que des boucles de ce genre
prédominent, ou au moins, c'est elles qui font prèsque toujours
le chemin critique pour la performance. Il y a eu pas mal de
recherche sur les possibilités de les paralleliser, et les
exigeances du compilateur pour le faire ont en partie
conditionné l'évolution de Fortran.
Le moindre pointeur dans ta boucle empêche le compilateur de
savoir quelle est la donnée qu'il manipule et si deux
pointeurs sont utilisés, il ne peut pas savoir s'ils ne
pointent pas effectivement sur la même donnée. Les références
constantes améliorent un peu les choses. Très peu.
Et voilà le problème dans le C et le C++. Le fait que les
tableaux deviennent très vite des pointeurs, et que le
compilateur ne peut paralleliser que s'il peut établir que les
tableaux (designés par des pointeurs) ne se recouvrent pas.
J'ai entendu vaguement parler des recherches à cet égard, il y a
un certain temps. Ce que j'ai entendu, c'est qu'il y avait bien
un compilateur expérimental qui faisait une optimisation
globale, en suivant la source des pointeurs, et qui savait que
des pointeurs qui sortaient de deux new distincts ne pouvaient
pas se recouvrir. Mais je n'en sais pas plus ; je l'ai entendu
en passant dans un couloir.
En principe, c'est possible. Dans la pratique, c'est bigrement
difficile.
L'autre problème qui se pose alors est le volume de calcul
nécessaire (grainsize) pour que le parallélisme puisse être
efficace. Si ta boucle est trop petite (=pas beaucoup
d'instructions), tu seras peut-être parallèle, mais au final
tu ne gagneras rien voire tu perdas du temps à créer tes
threads et à les synchroniser.
C'est vrai si tu veux travailler au niveau Posix (ou de l'API
Windows). Au niveau hardware, il existe en général des
possibilités d'une synchronisation mois chère.
On Jun 18, 10:32 pm, Ivan Dutka-Malen <none@nowhere> wrote:
Je pense que tu peux oublier tout rêve de compilateur
parallélisant. L'analyse d'un code pour en extraire un
parallélisme efficace est extrèmement complexe et ne
fonctionne en pratique que sur des boucles très simples avec
des données (notamment des tableaux) que le compilateur peut
aisément décomposer pour faire naître du parallélisme.
Concrètement, cela signifie qu'en dehors de boucles du type
SAXPY (S = A*X + Y) avec un pas d'accès (stride) regulier
(idéalement 1), où les tableaux (S, A, X et Y) sont non
recouvrants et vus comme tels par le compilateur, le
compilateur choisit la solution de prudence et laisse tout
séquentiel.
Dans la calcule numérique, il paraît que des boucles de ce genre
prédominent, ou au moins, c'est elles qui font prèsque toujours
le chemin critique pour la performance. Il y a eu pas mal de
recherche sur les possibilités de les paralleliser, et les
exigeances du compilateur pour le faire ont en partie
conditionné l'évolution de Fortran.
Le moindre pointeur dans ta boucle empêche le compilateur de
savoir quelle est la donnée qu'il manipule et si deux
pointeurs sont utilisés, il ne peut pas savoir s'ils ne
pointent pas effectivement sur la même donnée. Les références
constantes améliorent un peu les choses. Très peu.
Et voilà le problème dans le C et le C++. Le fait que les
tableaux deviennent très vite des pointeurs, et que le
compilateur ne peut paralleliser que s'il peut établir que les
tableaux (designés par des pointeurs) ne se recouvrent pas.
J'ai entendu vaguement parler des recherches à cet égard, il y a
un certain temps. Ce que j'ai entendu, c'est qu'il y avait bien
un compilateur expérimental qui faisait une optimisation
globale, en suivant la source des pointeurs, et qui savait que
des pointeurs qui sortaient de deux new distincts ne pouvaient
pas se recouvrir. Mais je n'en sais pas plus ; je l'ai entendu
en passant dans un couloir.
En principe, c'est possible. Dans la pratique, c'est bigrement
difficile.
L'autre problème qui se pose alors est le volume de calcul
nécessaire (grainsize) pour que le parallélisme puisse être
efficace. Si ta boucle est trop petite (=pas beaucoup
d'instructions), tu seras peut-être parallèle, mais au final
tu ne gagneras rien voire tu perdas du temps à créer tes
threads et à les synchroniser.
C'est vrai si tu veux travailler au niveau Posix (ou de l'API
Windows). Au niveau hardware, il existe en général des
possibilités d'une synchronisation mois chère.
On Jun 18, 10:32 pm, Ivan Dutka-Malen wrote:Je pense que tu peux oublier tout rêve de compilateur
parallélisant. L'analyse d'un code pour en extraire un
parallélisme efficace est extrèmement complexe et ne
fonctionne en pratique que sur des boucles très simples avec
des données (notamment des tableaux) que le compilateur peut
aisément décomposer pour faire naître du parallélisme.
Concrètement, cela signifie qu'en dehors de boucles du type
SAXPY (S = A*X + Y) avec un pas d'accès (stride) regulier
(idéalement 1), où les tableaux (S, A, X et Y) sont non
recouvrants et vus comme tels par le compilateur, le
compilateur choisit la solution de prudence et laisse tout
séquentiel.
Dans la calcule numérique, il paraît que des boucles de ce genre
prédominent, ou au moins, c'est elles qui font prèsque toujours
le chemin critique pour la performance. Il y a eu pas mal de
recherche sur les possibilités de les paralleliser, et les
exigeances du compilateur pour le faire ont en partie
conditionné l'évolution de Fortran.
Le moindre pointeur dans ta boucle empêche le compilateur de
savoir quelle est la donnée qu'il manipule et si deux
pointeurs sont utilisés, il ne peut pas savoir s'ils ne
pointent pas effectivement sur la même donnée. Les références
constantes améliorent un peu les choses. Très peu.
Et voilà le problème dans le C et le C++. Le fait que les
tableaux deviennent très vite des pointeurs, et que le
compilateur ne peut paralleliser que s'il peut établir que les
tableaux (designés par des pointeurs) ne se recouvrent pas.
J'ai entendu vaguement parler des recherches à cet égard, il y a
un certain temps. Ce que j'ai entendu, c'est qu'il y avait bien
un compilateur expérimental qui faisait une optimisation
globale, en suivant la source des pointeurs, et qui savait que
des pointeurs qui sortaient de deux new distincts ne pouvaient
pas se recouvrir. Mais je n'en sais pas plus ; je l'ai entendu
en passant dans un couloir.
En principe, c'est possible. Dans la pratique, c'est bigrement
difficile.
L'autre problème qui se pose alors est le volume de calcul
nécessaire (grainsize) pour que le parallélisme puisse être
efficace. Si ta boucle est trop petite (=pas beaucoup
d'instructions), tu seras peut-être parallèle, mais au final
tu ne gagneras rien voire tu perdas du temps à créer tes
threads et à les synchroniser.
C'est vrai si tu veux travailler au niveau Posix (ou de l'API
Windows). Au niveau hardware, il existe en général des
possibilités d'une synchronisation mois chère.
Et voilà le problème dans le C et le C++. Le fait que les
tableaux deviennent très vite des pointeurs, et que le
compilateur ne peut paralleliser que s'il peut établir que les
tableaux (designés par des pointeurs) ne se recouvrent pas.
Et voilà le problème dans le C et le C++. Le fait que les
tableaux deviennent très vite des pointeurs, et que le
compilateur ne peut paralleliser que s'il peut établir que les
tableaux (designés par des pointeurs) ne se recouvrent pas.
Et voilà le problème dans le C et le C++. Le fait que les
tableaux deviennent très vite des pointeurs, et que le
compilateur ne peut paralleliser que s'il peut établir que les
tableaux (designés par des pointeurs) ne se recouvrent pas.
On Thu, 19 Jun 2008 00:53:47 -0700 (PDT), James Kanze
:
>Et voilà le problème dans le C et le C++. Le fait que les
>tableaux deviennent très vite des pointeurs, et que le
>compilateur ne peut paralleliser que s'il peut établir que les
>tableaux (designés par des pointeurs) ne se recouvrent pas.
N'est-il pas envisageable de remplacer vector<> et compagnie
par une classe qui aurait les bonnes propriétés ? Ça peut être
une classe propriétaire, adaptée à un compilo, et que le
compilo reconnaît.
On Thu, 19 Jun 2008 00:53:47 -0700 (PDT), James Kanze
<james.ka...@gmail.com>:
>Et voilà le problème dans le C et le C++. Le fait que les
>tableaux deviennent très vite des pointeurs, et que le
>compilateur ne peut paralleliser que s'il peut établir que les
>tableaux (designés par des pointeurs) ne se recouvrent pas.
N'est-il pas envisageable de remplacer vector<> et compagnie
par une classe qui aurait les bonnes propriétés ? Ça peut être
une classe propriétaire, adaptée à un compilo, et que le
compilo reconnaît.
On Thu, 19 Jun 2008 00:53:47 -0700 (PDT), James Kanze
:
>Et voilà le problème dans le C et le C++. Le fait que les
>tableaux deviennent très vite des pointeurs, et que le
>compilateur ne peut paralleliser que s'il peut établir que les
>tableaux (designés par des pointeurs) ne se recouvrent pas.
N'est-il pas envisageable de remplacer vector<> et compagnie
par une classe qui aurait les bonnes propriétés ? Ça peut être
une classe propriétaire, adaptée à un compilo, et que le
compilo reconnaît.
... ne pas se servir des
itérateurs:-).
... ne pas se servir des
itérateurs:-).
... ne pas se servir des
itérateurs:-).
James Kanze a écrit :
> On Jun 18, 10:32 pm, Ivan Dutka-Malen wrote:
> Dans la calcule numérique, il paraît que des boucles de ce
> genre prédominent, ou au moins, c'est elles qui font prèsque
> toujours le chemin critique pour la performance. Il y a eu
> pas mal de recherche sur les possibilités de les
> paralleliser, et les exigeances du compilateur pour le faire
> ont en partie conditionné l'évolution de Fortran.
Oui et non. Cela dépend du type de calcul numérique que tu
réalises. Si ton calcul peut se réduire à la résolution d'un
système linéaire Ax=b (A matrice, x et b vecteurs) alors tu es
dans le cas le plus fréquemment traité. Il existe des tas de
solveurs différents, chacun adapté à un cas de figure (matrice
pleine, creuse, bande, hiérarchique, mal conditionnée, etc.)
et la littérature est abondante. Je dirai que c'est le cas
facile et le plus souvent pour ne pas réinventer l'eau chaude
on utilise des bibliothèques toutes faites (Linpack, Lapack,
Scalapack, etc.). Tu rencontres par exemple ce genre de
résolution dans les codes éléments finis (mécanique des
structures, des fluides, électromagnétisme et j'en passe).
Mais il existe aussi des tas de codes qui ne rentrent pas dans
ce moule. Juste pour l'exemple, je travaille sur un code qui
fait du calcul probabiliste et il n'y a (presque) rien qui
ressemble à un Ax=b dedans. Par contre pour ce qui est des
nombres aléatoires, ça y va... Tu as aussi les codes qui font
du gather/scatter, c'est-à-dire de l'indirection d'indice, en
particulier les codes éléments finis qui font de l'Ax=B ! Ex:
// A,B et I sont des tableaux, N la taille de ce petit monde-là
for( size_t i=0; i<N; ++i) A[ I[i] ] = B[ i ];
Tu ne peux pas savoir si I[i] != I[j] (i!=j), donc tu ne peux pas
paralléliser car tu auras un conflit de données sur A.
Il se trouve aussi que les codes scientifiques ont
généralement une longue histoire. Beaucoup ont plusieurs
années, voire plusieurs décennies, au compteur. Ce qui fait
qu'il ont été créés au moment où les machines vectorielles
(Cray, Nec, Fujitsu, etc.) avaient leur heure de gloire.
C'était aussi la période où tous les algorithmes qui tentaient
le pari du calcul intensif ont connu leurs meilleures
implémentations. On a donc produit des codes adaptés à des
machines qui voyaient tout à travers la notion de vecteur. Or
le coût de réécriture d'un tel code est souvent prohibitif et
on ne le fait pas. Le mode de pensée a aussi été fortement
conditionné et les numériciens ont pris l'habitude de tout
vectoriser.
>> Le moindre pointeur dans ta boucle empêche le compilateur de
>> savoir quelle est la donnée qu'il manipule et si deux
>> pointeurs sont utilisés, il ne peut pas savoir s'ils ne
>> pointent pas effectivement sur la même donnée. Les références
>> constantes améliorent un peu les choses. Très peu.
> Et voilà le problème dans le C et le C++. Le fait que les
> tableaux deviennent très vite des pointeurs, et que le
> compilateur ne peut paralleliser que s'il peut établir que les
> tableaux (designés par des pointeurs) ne se recouvrent pas.
Mais le FORTRAN n'est pas mieux loti avec son instruction
EQUIVALENCE qui bousille l'antialiasing des données...
> J'ai entendu vaguement parler des recherches à cet égard, il
> y a un certain temps. Ce que j'ai entendu, c'est qu'il y
> avait bien un compilateur expérimental qui faisait une
> optimisation globale, en suivant la source des pointeurs, et
> qui savait que des pointeurs qui sortaient de deux new
> distincts ne pouvaient pas se recouvrir. Mais je n'en sais
> pas plus ; je l'ai entendu en passant dans un couloir.
A condition que les new aient lieu pas trop loin de la boucle à
optimiser.
Mais les codes numériques allouent généralement les données en
bloc au début, à la lecture des fichiers d'entrée, ce qui fait
qu'au bout de quelques fonctions, le compilateur est largué ne
serait-ce que par la pile d'appel qui devient gigantesque à
traiter.
Si en plus tu fais de la compilation en unités séparées (= une
fonction par fichier), le compilo ne peut plus suivre le lien
et l'analyse interprocédurale ne pourra se faire qu'au link au
mieux.
Sans compter aussi que les personnes qui ont écrit les codes
un peu anciens étaient souvent obsédés par la mémoire, et
qu'ils réutilisaient souvent les structures de données pour y
mettre tout et n'importe quoi. Si je te faisais le catalogue
de ce que j'ai vu, tu aurais de la lecture (amusante) pour le
reste de la soirée. Si un humain n'arrive pas à suivre ce
qu'on met dans un tableau, je ne te parle pas du pauvre
compilo qui ne sait même pas ce qu'il manipule...
> En principe, c'est possible. Dans la pratique, c'est bigrement
> difficile.
Comme tu dis...
>> L'autre problème qui se pose alors est le volume de calcul
>> nécessaire (grainsize) pour que le parallélisme puisse être
>> efficace. Si ta boucle est trop petite (=pas beaucoup
>> d'instructions), tu seras peut-être parallèle, mais au final
>> tu ne gagneras rien voire tu perdas du temps à créer tes
>> threads et à les synchroniser.
> C'est vrai si tu veux travailler au niveau Posix (ou de l'API
> Windows). Au niveau hardware, il existe en général des
> possibilités d'une synchronisation mois chère.
Ceci est vrai avec tous les threads quelle que soit
l'implémentation. Le problème est inhérent au parallélisme et
à la gestion de la dépendance entre les données (=je dois
attendre que la données D soit produite avant de pouvoir
l'utiliser).
Mais je ne vois pas ce que tu veux dire avec le niveau hardware.
James Kanze a écrit :
> On Jun 18, 10:32 pm, Ivan Dutka-Malen <none@nowhere> wrote:
> Dans la calcule numérique, il paraît que des boucles de ce
> genre prédominent, ou au moins, c'est elles qui font prèsque
> toujours le chemin critique pour la performance. Il y a eu
> pas mal de recherche sur les possibilités de les
> paralleliser, et les exigeances du compilateur pour le faire
> ont en partie conditionné l'évolution de Fortran.
Oui et non. Cela dépend du type de calcul numérique que tu
réalises. Si ton calcul peut se réduire à la résolution d'un
système linéaire Ax=b (A matrice, x et b vecteurs) alors tu es
dans le cas le plus fréquemment traité. Il existe des tas de
solveurs différents, chacun adapté à un cas de figure (matrice
pleine, creuse, bande, hiérarchique, mal conditionnée, etc.)
et la littérature est abondante. Je dirai que c'est le cas
facile et le plus souvent pour ne pas réinventer l'eau chaude
on utilise des bibliothèques toutes faites (Linpack, Lapack,
Scalapack, etc.). Tu rencontres par exemple ce genre de
résolution dans les codes éléments finis (mécanique des
structures, des fluides, électromagnétisme et j'en passe).
Mais il existe aussi des tas de codes qui ne rentrent pas dans
ce moule. Juste pour l'exemple, je travaille sur un code qui
fait du calcul probabiliste et il n'y a (presque) rien qui
ressemble à un Ax=b dedans. Par contre pour ce qui est des
nombres aléatoires, ça y va... Tu as aussi les codes qui font
du gather/scatter, c'est-à-dire de l'indirection d'indice, en
particulier les codes éléments finis qui font de l'Ax=B ! Ex:
// A,B et I sont des tableaux, N la taille de ce petit monde-là
for( size_t i=0; i<N; ++i) A[ I[i] ] = B[ i ];
Tu ne peux pas savoir si I[i] != I[j] (i!=j), donc tu ne peux pas
paralléliser car tu auras un conflit de données sur A.
Il se trouve aussi que les codes scientifiques ont
généralement une longue histoire. Beaucoup ont plusieurs
années, voire plusieurs décennies, au compteur. Ce qui fait
qu'il ont été créés au moment où les machines vectorielles
(Cray, Nec, Fujitsu, etc.) avaient leur heure de gloire.
C'était aussi la période où tous les algorithmes qui tentaient
le pari du calcul intensif ont connu leurs meilleures
implémentations. On a donc produit des codes adaptés à des
machines qui voyaient tout à travers la notion de vecteur. Or
le coût de réécriture d'un tel code est souvent prohibitif et
on ne le fait pas. Le mode de pensée a aussi été fortement
conditionné et les numériciens ont pris l'habitude de tout
vectoriser.
>> Le moindre pointeur dans ta boucle empêche le compilateur de
>> savoir quelle est la donnée qu'il manipule et si deux
>> pointeurs sont utilisés, il ne peut pas savoir s'ils ne
>> pointent pas effectivement sur la même donnée. Les références
>> constantes améliorent un peu les choses. Très peu.
> Et voilà le problème dans le C et le C++. Le fait que les
> tableaux deviennent très vite des pointeurs, et que le
> compilateur ne peut paralleliser que s'il peut établir que les
> tableaux (designés par des pointeurs) ne se recouvrent pas.
Mais le FORTRAN n'est pas mieux loti avec son instruction
EQUIVALENCE qui bousille l'antialiasing des données...
> J'ai entendu vaguement parler des recherches à cet égard, il
> y a un certain temps. Ce que j'ai entendu, c'est qu'il y
> avait bien un compilateur expérimental qui faisait une
> optimisation globale, en suivant la source des pointeurs, et
> qui savait que des pointeurs qui sortaient de deux new
> distincts ne pouvaient pas se recouvrir. Mais je n'en sais
> pas plus ; je l'ai entendu en passant dans un couloir.
A condition que les new aient lieu pas trop loin de la boucle à
optimiser.
Mais les codes numériques allouent généralement les données en
bloc au début, à la lecture des fichiers d'entrée, ce qui fait
qu'au bout de quelques fonctions, le compilateur est largué ne
serait-ce que par la pile d'appel qui devient gigantesque à
traiter.
Si en plus tu fais de la compilation en unités séparées (= une
fonction par fichier), le compilo ne peut plus suivre le lien
et l'analyse interprocédurale ne pourra se faire qu'au link au
mieux.
Sans compter aussi que les personnes qui ont écrit les codes
un peu anciens étaient souvent obsédés par la mémoire, et
qu'ils réutilisaient souvent les structures de données pour y
mettre tout et n'importe quoi. Si je te faisais le catalogue
de ce que j'ai vu, tu aurais de la lecture (amusante) pour le
reste de la soirée. Si un humain n'arrive pas à suivre ce
qu'on met dans un tableau, je ne te parle pas du pauvre
compilo qui ne sait même pas ce qu'il manipule...
> En principe, c'est possible. Dans la pratique, c'est bigrement
> difficile.
Comme tu dis...
>> L'autre problème qui se pose alors est le volume de calcul
>> nécessaire (grainsize) pour que le parallélisme puisse être
>> efficace. Si ta boucle est trop petite (=pas beaucoup
>> d'instructions), tu seras peut-être parallèle, mais au final
>> tu ne gagneras rien voire tu perdas du temps à créer tes
>> threads et à les synchroniser.
> C'est vrai si tu veux travailler au niveau Posix (ou de l'API
> Windows). Au niveau hardware, il existe en général des
> possibilités d'une synchronisation mois chère.
Ceci est vrai avec tous les threads quelle que soit
l'implémentation. Le problème est inhérent au parallélisme et
à la gestion de la dépendance entre les données (=je dois
attendre que la données D soit produite avant de pouvoir
l'utiliser).
Mais je ne vois pas ce que tu veux dire avec le niveau hardware.
James Kanze a écrit :
> On Jun 18, 10:32 pm, Ivan Dutka-Malen wrote:
> Dans la calcule numérique, il paraît que des boucles de ce
> genre prédominent, ou au moins, c'est elles qui font prèsque
> toujours le chemin critique pour la performance. Il y a eu
> pas mal de recherche sur les possibilités de les
> paralleliser, et les exigeances du compilateur pour le faire
> ont en partie conditionné l'évolution de Fortran.
Oui et non. Cela dépend du type de calcul numérique que tu
réalises. Si ton calcul peut se réduire à la résolution d'un
système linéaire Ax=b (A matrice, x et b vecteurs) alors tu es
dans le cas le plus fréquemment traité. Il existe des tas de
solveurs différents, chacun adapté à un cas de figure (matrice
pleine, creuse, bande, hiérarchique, mal conditionnée, etc.)
et la littérature est abondante. Je dirai que c'est le cas
facile et le plus souvent pour ne pas réinventer l'eau chaude
on utilise des bibliothèques toutes faites (Linpack, Lapack,
Scalapack, etc.). Tu rencontres par exemple ce genre de
résolution dans les codes éléments finis (mécanique des
structures, des fluides, électromagnétisme et j'en passe).
Mais il existe aussi des tas de codes qui ne rentrent pas dans
ce moule. Juste pour l'exemple, je travaille sur un code qui
fait du calcul probabiliste et il n'y a (presque) rien qui
ressemble à un Ax=b dedans. Par contre pour ce qui est des
nombres aléatoires, ça y va... Tu as aussi les codes qui font
du gather/scatter, c'est-à-dire de l'indirection d'indice, en
particulier les codes éléments finis qui font de l'Ax=B ! Ex:
// A,B et I sont des tableaux, N la taille de ce petit monde-là
for( size_t i=0; i<N; ++i) A[ I[i] ] = B[ i ];
Tu ne peux pas savoir si I[i] != I[j] (i!=j), donc tu ne peux pas
paralléliser car tu auras un conflit de données sur A.
Il se trouve aussi que les codes scientifiques ont
généralement une longue histoire. Beaucoup ont plusieurs
années, voire plusieurs décennies, au compteur. Ce qui fait
qu'il ont été créés au moment où les machines vectorielles
(Cray, Nec, Fujitsu, etc.) avaient leur heure de gloire.
C'était aussi la période où tous les algorithmes qui tentaient
le pari du calcul intensif ont connu leurs meilleures
implémentations. On a donc produit des codes adaptés à des
machines qui voyaient tout à travers la notion de vecteur. Or
le coût de réécriture d'un tel code est souvent prohibitif et
on ne le fait pas. Le mode de pensée a aussi été fortement
conditionné et les numériciens ont pris l'habitude de tout
vectoriser.
>> Le moindre pointeur dans ta boucle empêche le compilateur de
>> savoir quelle est la donnée qu'il manipule et si deux
>> pointeurs sont utilisés, il ne peut pas savoir s'ils ne
>> pointent pas effectivement sur la même donnée. Les références
>> constantes améliorent un peu les choses. Très peu.
> Et voilà le problème dans le C et le C++. Le fait que les
> tableaux deviennent très vite des pointeurs, et que le
> compilateur ne peut paralleliser que s'il peut établir que les
> tableaux (designés par des pointeurs) ne se recouvrent pas.
Mais le FORTRAN n'est pas mieux loti avec son instruction
EQUIVALENCE qui bousille l'antialiasing des données...
> J'ai entendu vaguement parler des recherches à cet égard, il
> y a un certain temps. Ce que j'ai entendu, c'est qu'il y
> avait bien un compilateur expérimental qui faisait une
> optimisation globale, en suivant la source des pointeurs, et
> qui savait que des pointeurs qui sortaient de deux new
> distincts ne pouvaient pas se recouvrir. Mais je n'en sais
> pas plus ; je l'ai entendu en passant dans un couloir.
A condition que les new aient lieu pas trop loin de la boucle à
optimiser.
Mais les codes numériques allouent généralement les données en
bloc au début, à la lecture des fichiers d'entrée, ce qui fait
qu'au bout de quelques fonctions, le compilateur est largué ne
serait-ce que par la pile d'appel qui devient gigantesque à
traiter.
Si en plus tu fais de la compilation en unités séparées (= une
fonction par fichier), le compilo ne peut plus suivre le lien
et l'analyse interprocédurale ne pourra se faire qu'au link au
mieux.
Sans compter aussi que les personnes qui ont écrit les codes
un peu anciens étaient souvent obsédés par la mémoire, et
qu'ils réutilisaient souvent les structures de données pour y
mettre tout et n'importe quoi. Si je te faisais le catalogue
de ce que j'ai vu, tu aurais de la lecture (amusante) pour le
reste de la soirée. Si un humain n'arrive pas à suivre ce
qu'on met dans un tableau, je ne te parle pas du pauvre
compilo qui ne sait même pas ce qu'il manipule...
> En principe, c'est possible. Dans la pratique, c'est bigrement
> difficile.
Comme tu dis...
>> L'autre problème qui se pose alors est le volume de calcul
>> nécessaire (grainsize) pour que le parallélisme puisse être
>> efficace. Si ta boucle est trop petite (=pas beaucoup
>> d'instructions), tu seras peut-être parallèle, mais au final
>> tu ne gagneras rien voire tu perdas du temps à créer tes
>> threads et à les synchroniser.
> C'est vrai si tu veux travailler au niveau Posix (ou de l'API
> Windows). Au niveau hardware, il existe en général des
> possibilités d'une synchronisation mois chère.
Ceci est vrai avec tous les threads quelle que soit
l'implémentation. Le problème est inhérent au parallélisme et
à la gestion de la dépendance entre les données (=je dois
attendre que la données D soit produite avant de pouvoir
l'utiliser).
Mais je ne vois pas ce que tu veux dire avec le niveau hardware.