Pierre Maurette wrote:
[...]
Cette option, elle signifie en gros: "Compilo, nom ami, je te
jure que ne fais pas l'abruti en modifiant en loucedé mes
variable par des pointeurs occultes (et des __asm ?), optimise
à ta guise". L'exemple donné n'est pas convaincant (il suffit
de faire l'addition avant la boucle). Mais dans d'autres cas,
pourquoi pas ?. En #pragma, bien sûr.
Si tu parles de l'exemple dans la doc Microsoft dont tu as posté
le lien, il est bien convaincant. L'expression dans la boucle,
c'est : « *p = x + y ». Et justement, si p pointe à x ou à y, il
faut que le compilateur fasse l'addition chaque fois dans la
boucle ; ce n'est que dans l'absence établie (par preuve ou par
déclaration sur l'honneur du programmeur) de cette possibilité
que le compilateur peut enlever l'addition de la boucle.
Nous sommes d'accord. L'exemple est explicite *du danger*.
Au fur et à mésure que le parallelisme des processeurs augmente,
le problème devient plus aigu. Considérons la boucle suivante :
for ( int i = 0 ; i < 1000000 ; ++ i ) {
a[ i ] = b[ i ] + c[ i ] ;
}
Sur un processeur hyperthreadé, un compilateur Java ou Ada
pourrait splitter la boucle en deux, en l'exécutant pour les
indices paires dans un thread, et pour les indices impaires dans
l'autre. Si la boucle est dans une fonction, et a, b et c sont
en fait des pointeurs, un compilateur C ou C++ ne peut pas le
faire, parce qu'on aurait pu appeler la fonction avec quelque
chose comme (tab + 1, tab, tab).
Note bien que ni restrict, ni les options Microsoft n'aide ici,
parce qu'ils interdisent aussi l'appel (tab, tab, tab), qu'on
veut permettre.
Chez Microsoft, restera plus que les intrinsics sur 128 bits /16 ou 32
Pierre Maurette wrote:
[...]
Cette option, elle signifie en gros: "Compilo, nom ami, je te
jure que ne fais pas l'abruti en modifiant en loucedé mes
variable par des pointeurs occultes (et des __asm ?), optimise
à ta guise". L'exemple donné n'est pas convaincant (il suffit
de faire l'addition avant la boucle). Mais dans d'autres cas,
pourquoi pas ?. En #pragma, bien sûr.
Si tu parles de l'exemple dans la doc Microsoft dont tu as posté
le lien, il est bien convaincant. L'expression dans la boucle,
c'est : « *p = x + y ». Et justement, si p pointe à x ou à y, il
faut que le compilateur fasse l'addition chaque fois dans la
boucle ; ce n'est que dans l'absence établie (par preuve ou par
déclaration sur l'honneur du programmeur) de cette possibilité
que le compilateur peut enlever l'addition de la boucle.
Nous sommes d'accord. L'exemple est explicite *du danger*.
Au fur et à mésure que le parallelisme des processeurs augmente,
le problème devient plus aigu. Considérons la boucle suivante :
for ( int i = 0 ; i < 1000000 ; ++ i ) {
a[ i ] = b[ i ] + c[ i ] ;
}
Sur un processeur hyperthreadé, un compilateur Java ou Ada
pourrait splitter la boucle en deux, en l'exécutant pour les
indices paires dans un thread, et pour les indices impaires dans
l'autre. Si la boucle est dans une fonction, et a, b et c sont
en fait des pointeurs, un compilateur C ou C++ ne peut pas le
faire, parce qu'on aurait pu appeler la fonction avec quelque
chose comme (tab + 1, tab, tab).
Note bien que ni restrict, ni les options Microsoft n'aide ici,
parce qu'ils interdisent aussi l'appel (tab, tab, tab), qu'on
veut permettre.
Chez Microsoft, restera plus que les intrinsics sur 128 bits /16 ou 32
Pierre Maurette wrote:
[...]
Cette option, elle signifie en gros: "Compilo, nom ami, je te
jure que ne fais pas l'abruti en modifiant en loucedé mes
variable par des pointeurs occultes (et des __asm ?), optimise
à ta guise". L'exemple donné n'est pas convaincant (il suffit
de faire l'addition avant la boucle). Mais dans d'autres cas,
pourquoi pas ?. En #pragma, bien sûr.
Si tu parles de l'exemple dans la doc Microsoft dont tu as posté
le lien, il est bien convaincant. L'expression dans la boucle,
c'est : « *p = x + y ». Et justement, si p pointe à x ou à y, il
faut que le compilateur fasse l'addition chaque fois dans la
boucle ; ce n'est que dans l'absence établie (par preuve ou par
déclaration sur l'honneur du programmeur) de cette possibilité
que le compilateur peut enlever l'addition de la boucle.
Nous sommes d'accord. L'exemple est explicite *du danger*.
Au fur et à mésure que le parallelisme des processeurs augmente,
le problème devient plus aigu. Considérons la boucle suivante :
for ( int i = 0 ; i < 1000000 ; ++ i ) {
a[ i ] = b[ i ] + c[ i ] ;
}
Sur un processeur hyperthreadé, un compilateur Java ou Ada
pourrait splitter la boucle en deux, en l'exécutant pour les
indices paires dans un thread, et pour les indices impaires dans
l'autre. Si la boucle est dans une fonction, et a, b et c sont
en fait des pointeurs, un compilateur C ou C++ ne peut pas le
faire, parce qu'on aurait pu appeler la fonction avec quelque
chose comme (tab + 1, tab, tab).
Note bien que ni restrict, ni les options Microsoft n'aide ici,
parce qu'ils interdisent aussi l'appel (tab, tab, tab), qu'on
veut permettre.
Chez Microsoft, restera plus que les intrinsics sur 128 bits /16 ou 32
for ( int i = 0 ; i < 1000000 ; ++ i ) {
a[ i ] = b[ i ] + c[ i ] ;
}
Sur un processeur hyperthreadé, un compilateur Java ou Ada
pourrait splitter la boucle en deux, en l'exécutant pour les
indices paires dans un thread, et pour les indices impaires dans
l'autre. Si la boucle est dans une fonction, et a, b et c sont
en fait des pointeurs, un compilateur C ou C++ ne peut pas le
faire, parce qu'on aurait pu appeler la fonction avec quelque
chose comme (tab + 1, tab, tab).
for ( int i = 0 ; i < 1000000 ; ++ i ) {
a[ i ] = b[ i ] + c[ i ] ;
}
Sur un processeur hyperthreadé, un compilateur Java ou Ada
pourrait splitter la boucle en deux, en l'exécutant pour les
indices paires dans un thread, et pour les indices impaires dans
l'autre. Si la boucle est dans une fonction, et a, b et c sont
en fait des pointeurs, un compilateur C ou C++ ne peut pas le
faire, parce qu'on aurait pu appeler la fonction avec quelque
chose comme (tab + 1, tab, tab).
for ( int i = 0 ; i < 1000000 ; ++ i ) {
a[ i ] = b[ i ] + c[ i ] ;
}
Sur un processeur hyperthreadé, un compilateur Java ou Ada
pourrait splitter la boucle en deux, en l'exécutant pour les
indices paires dans un thread, et pour les indices impaires dans
l'autre. Si la boucle est dans une fonction, et a, b et c sont
en fait des pointeurs, un compilateur C ou C++ ne peut pas le
faire, parce qu'on aurait pu appeler la fonction avec quelque
chose comme (tab + 1, tab, tab).
le compilateur ne pourrait-il pas générer le code pour les 2 cas (suppose
aucun alias // aucune supposition), lorsque la fonction est appelée faire
un branchement selon qu'il peut utiliser le code optimisé ou non ?
ça me semble simple et guère moins efficace même lorsque l'on pourrait
utiliser un /Og
Ça pourrait générer des surprises lors d'un débogage, surtout crapuleux
le compilateur ne pourrait-il pas générer le code pour les 2 cas (suppose
aucun alias // aucune supposition), lorsque la fonction est appelée faire
un branchement selon qu'il peut utiliser le code optimisé ou non ?
ça me semble simple et guère moins efficace même lorsque l'on pourrait
utiliser un /Og
Ça pourrait générer des surprises lors d'un débogage, surtout crapuleux
le compilateur ne pourrait-il pas générer le code pour les 2 cas (suppose
aucun alias // aucune supposition), lorsque la fonction est appelée faire
un branchement selon qu'il peut utiliser le code optimisé ou non ?
ça me semble simple et guère moins efficace même lorsque l'on pourrait
utiliser un /Og
Ça pourrait générer des surprises lors d'un débogage, surtout crapuleux
(10 May 2005 11:51,for ( int i = 0 ; i < 1000000 ; ++ i ) {
a[ i ] = b[ i ] + c[ i ] ;
}
Sur un processeur hyperthreadé, un compilateur Java ou Ada
pourrait splitter la boucle en deux, en l'exécutant pour les
indices paires dans un thread, et pour les indices impaires
dans l'autre. Si la boucle est dans une fonction, et a, b et
c sont en fait des pointeurs, un compilateur C ou C++ ne
peut pas le faire, parce qu'on aurait pu appeler la fonction
avec quelque chose comme (tab + 1, tab, tab).
le compilateur ne pourrait-il pas générer le code pour les 2
cas (suppose aucun alias // aucune supposition), lorsque la
fonction est appelée faire un branchement selon qu'il peut
utiliser le code optimisé ou non ?
ça me semble simple et guère moins efficace même lorsque l'on
pourrait utiliser un /Og
kanze@gabi-soft.fr (10 May 2005 11:51,
for ( int i = 0 ; i < 1000000 ; ++ i ) {
a[ i ] = b[ i ] + c[ i ] ;
}
Sur un processeur hyperthreadé, un compilateur Java ou Ada
pourrait splitter la boucle en deux, en l'exécutant pour les
indices paires dans un thread, et pour les indices impaires
dans l'autre. Si la boucle est dans une fonction, et a, b et
c sont en fait des pointeurs, un compilateur C ou C++ ne
peut pas le faire, parce qu'on aurait pu appeler la fonction
avec quelque chose comme (tab + 1, tab, tab).
le compilateur ne pourrait-il pas générer le code pour les 2
cas (suppose aucun alias // aucune supposition), lorsque la
fonction est appelée faire un branchement selon qu'il peut
utiliser le code optimisé ou non ?
ça me semble simple et guère moins efficace même lorsque l'on
pourrait utiliser un /Og
(10 May 2005 11:51,for ( int i = 0 ; i < 1000000 ; ++ i ) {
a[ i ] = b[ i ] + c[ i ] ;
}
Sur un processeur hyperthreadé, un compilateur Java ou Ada
pourrait splitter la boucle en deux, en l'exécutant pour les
indices paires dans un thread, et pour les indices impaires
dans l'autre. Si la boucle est dans une fonction, et a, b et
c sont en fait des pointeurs, un compilateur C ou C++ ne
peut pas le faire, parce qu'on aurait pu appeler la fonction
avec quelque chose comme (tab + 1, tab, tab).
le compilateur ne pourrait-il pas générer le code pour les 2
cas (suppose aucun alias // aucune supposition), lorsque la
fonction est appelée faire un branchement selon qu'il peut
utiliser le code optimisé ou non ?
ça me semble simple et guère moins efficace même lorsque l'on
pourrait utiliser un /Og
[...]le compilateur ne pourrait-il pas générer le code pour les 2
cas (suppose aucun alias // aucune supposition), lorsque la
fonction est appelée faire un branchement selon qu'il peut
utiliser le code optimisé ou non ?
ça me semble simple et guère moins efficace même lorsque
l'on pourrait utiliser un /Og
Ça pourrait générer des surprises lors d'un débogage, surtout
crapuleux ;-)
J'ai vu un truc comme ça sous VC7. C'était au cours de tests
dont j'ai parlé ici, voir si on pouvait par 'register'
favoriser une branche que le programmeur sait être prise
presqu'à chaque fois, alors que le compilateur ne peut pas le
supposer.
Puisqu'on est là dessus, je me pose une question : j'avais
pour habitude, parce que ça m'a paru plus facile pour les
makefile et fichiers de commande, de compiler sans lier, puis
de lier. Je me demande si cette manie peut empêcher des
optimisations ...
[...]
le compilateur ne pourrait-il pas générer le code pour les 2
cas (suppose aucun alias // aucune supposition), lorsque la
fonction est appelée faire un branchement selon qu'il peut
utiliser le code optimisé ou non ?
ça me semble simple et guère moins efficace même lorsque
l'on pourrait utiliser un /Og
Ça pourrait générer des surprises lors d'un débogage, surtout
crapuleux ;-)
J'ai vu un truc comme ça sous VC7. C'était au cours de tests
dont j'ai parlé ici, voir si on pouvait par 'register'
favoriser une branche que le programmeur sait être prise
presqu'à chaque fois, alors que le compilateur ne peut pas le
supposer.
Puisqu'on est là dessus, je me pose une question : j'avais
pour habitude, parce que ça m'a paru plus facile pour les
makefile et fichiers de commande, de compiler sans lier, puis
de lier. Je me demande si cette manie peut empêcher des
optimisations ...
[...]le compilateur ne pourrait-il pas générer le code pour les 2
cas (suppose aucun alias // aucune supposition), lorsque la
fonction est appelée faire un branchement selon qu'il peut
utiliser le code optimisé ou non ?
ça me semble simple et guère moins efficace même lorsque
l'on pourrait utiliser un /Og
Ça pourrait générer des surprises lors d'un débogage, surtout
crapuleux ;-)
J'ai vu un truc comme ça sous VC7. C'était au cours de tests
dont j'ai parlé ici, voir si on pouvait par 'register'
favoriser une branche que le programmeur sait être prise
presqu'à chaque fois, alors que le compilateur ne peut pas le
supposer.
Puisqu'on est là dessus, je me pose une question : j'avais
pour habitude, parce que ça m'a paru plus facile pour les
makefile et fichiers de commande, de compiler sans lier, puis
de lier. Je me demande si cette manie peut empêcher des
optimisations ...
Je ne vois pas ce que register pourrait avoir à faire dans
l'écoulement du programme. En fait, en général, le compilateur
(quand on veut de l'optimisation, évidemment) sait pertinemment
bien quelles branches sont les plus fréquents, parce qu'il a
accès aux informations du profileur. (Je ne sais pas pour VC++,
mais il me semble en avoir entendu parler. C'est bien le cas de
tous les compilateurs Unix, en tout cas.)
Pourtant, ça le fait, et ça optimise clairement avec gcc 3.2. Le
[...]Puisqu'on est là dessus, je me pose une question : j'avais
pour habitude, parce que ça m'a paru plus facile pour les
makefile et fichiers de commande, de compiler sans lier, puis
de lier. Je me demande si cette manie peut empêcher des
optimisations ...
L'optimisation finale aujourd'hui se fait lors de l'édition des
liens, sur tout le programme. Mais de toute façon, que tu
invoques « cl /Tp a.cc /Tp b.cc », ou que tu invoques le
compilateur deux fois, puis l'éditeur de liens, le programme
pilot (parce que c'est ce que c'est en réalité) appelle le
compilateur deux fois, et l'éditeur de liens une fois. Dans les
deux cas, exactement pareil.
Je ne vois pas ce que register pourrait avoir à faire dans
l'écoulement du programme. En fait, en général, le compilateur
(quand on veut de l'optimisation, évidemment) sait pertinemment
bien quelles branches sont les plus fréquents, parce qu'il a
accès aux informations du profileur. (Je ne sais pas pour VC++,
mais il me semble en avoir entendu parler. C'est bien le cas de
tous les compilateurs Unix, en tout cas.)
Pourtant, ça le fait, et ça optimise clairement avec gcc 3.2. Le
[...]
Puisqu'on est là dessus, je me pose une question : j'avais
pour habitude, parce que ça m'a paru plus facile pour les
makefile et fichiers de commande, de compiler sans lier, puis
de lier. Je me demande si cette manie peut empêcher des
optimisations ...
L'optimisation finale aujourd'hui se fait lors de l'édition des
liens, sur tout le programme. Mais de toute façon, que tu
invoques « cl /Tp a.cc /Tp b.cc », ou que tu invoques le
compilateur deux fois, puis l'éditeur de liens, le programme
pilot (parce que c'est ce que c'est en réalité) appelle le
compilateur deux fois, et l'éditeur de liens une fois. Dans les
deux cas, exactement pareil.
Je ne vois pas ce que register pourrait avoir à faire dans
l'écoulement du programme. En fait, en général, le compilateur
(quand on veut de l'optimisation, évidemment) sait pertinemment
bien quelles branches sont les plus fréquents, parce qu'il a
accès aux informations du profileur. (Je ne sais pas pour VC++,
mais il me semble en avoir entendu parler. C'est bien le cas de
tous les compilateurs Unix, en tout cas.)
Pourtant, ça le fait, et ça optimise clairement avec gcc 3.2. Le
[...]Puisqu'on est là dessus, je me pose une question : j'avais
pour habitude, parce que ça m'a paru plus facile pour les
makefile et fichiers de commande, de compiler sans lier, puis
de lier. Je me demande si cette manie peut empêcher des
optimisations ...
L'optimisation finale aujourd'hui se fait lors de l'édition des
liens, sur tout le programme. Mais de toute façon, que tu
invoques « cl /Tp a.cc /Tp b.cc », ou que tu invoques le
compilateur deux fois, puis l'éditeur de liens, le programme
pilot (parce que c'est ce que c'est en réalité) appelle le
compilateur deux fois, et l'éditeur de liens une fois. Dans les
deux cas, exactement pareil.
Je ne vois pas ce que register pourrait avoir à faire dans
l'écoulement du programme. En fait, en général, le compilateur
(quand on veut de l'optimisation, évidemment) sait pertinemment
bien quelles branches sont les plus fréquents, parce qu'il a
accès aux informations du profileur. (Je ne sais pas pour VC++,
mais il me semble en avoir entendu parler. C'est bien le cas de
tous les compilateurs Unix, en tout cas.)
Pourtant, ça le fait, et ça optimise clairement avec gcc 3.2.
Je ne vois pas ce que register pourrait avoir à faire dans
l'écoulement du programme. En fait, en général, le compilateur
(quand on veut de l'optimisation, évidemment) sait pertinemment
bien quelles branches sont les plus fréquents, parce qu'il a
accès aux informations du profileur. (Je ne sais pas pour VC++,
mais il me semble en avoir entendu parler. C'est bien le cas de
tous les compilateurs Unix, en tout cas.)
Pourtant, ça le fait, et ça optimise clairement avec gcc 3.2.
Je ne vois pas ce que register pourrait avoir à faire dans
l'écoulement du programme. En fait, en général, le compilateur
(quand on veut de l'optimisation, évidemment) sait pertinemment
bien quelles branches sont les plus fréquents, parce qu'il a
accès aux informations du profileur. (Je ne sais pas pour VC++,
mais il me semble en avoir entendu parler. C'est bien le cas de
tous les compilateurs Unix, en tout cas.)
Pourtant, ça le fait, et ça optimise clairement avec gcc 3.2.
N'oublions pas qu'on parle ici surtout des compilateurs pour des
processeurs parallels. Il y a peu, ça signifiait des Cray et companie.
N'oublions pas qu'on parle ici surtout des compilateurs pour des
processeurs parallels. Il y a peu, ça signifiait des Cray et companie.
N'oublions pas qu'on parle ici surtout des compilateurs pour des
processeurs parallels. Il y a peu, ça signifiait des Cray et companie.
N'oublions pas qu'on parle ici surtout des compilateurs pour des
processeurs parallels. Il y a peu, ça signifiait des Cray et
companie. Depuis peu, en revanche, il y a du hyper-threading sur
des PC. Il va falloir que les implémenteurs de compilateur s'y
mettent.
N'oublions pas qu'on parle ici surtout des compilateurs pour des
processeurs parallels. Il y a peu, ça signifiait des Cray et
companie. Depuis peu, en revanche, il y a du hyper-threading sur
des PC. Il va falloir que les implémenteurs de compilateur s'y
mettent.
N'oublions pas qu'on parle ici surtout des compilateurs pour des
processeurs parallels. Il y a peu, ça signifiait des Cray et
companie. Depuis peu, en revanche, il y a du hyper-threading sur
des PC. Il va falloir que les implémenteurs de compilateur s'y
mettent.
N'oublions pas qu'on parle ici surtout des compilateurs pour
des processeurs parallels. Il y a peu, ça signifiait des
Cray et companie.
Je croyais qu'il y avait pas mal de SMP dans les stations
Alpha, c'est quand même des machines un tantinet plus
répandues que les Cray, non ? Ou on optimise simplement pas
la compilation pour les SMP Alpha/Intel ? (ce serait con,
quand même)
N'oublions pas qu'on parle ici surtout des compilateurs pour
des processeurs parallels. Il y a peu, ça signifiait des
Cray et companie.
Je croyais qu'il y avait pas mal de SMP dans les stations
Alpha, c'est quand même des machines un tantinet plus
répandues que les Cray, non ? Ou on optimise simplement pas
la compilation pour les SMP Alpha/Intel ? (ce serait con,
quand même)
N'oublions pas qu'on parle ici surtout des compilateurs pour
des processeurs parallels. Il y a peu, ça signifiait des
Cray et companie.
Je croyais qu'il y avait pas mal de SMP dans les stations
Alpha, c'est quand même des machines un tantinet plus
répandues que les Cray, non ? Ou on optimise simplement pas
la compilation pour les SMP Alpha/Intel ? (ce serait con,
quand même)