Quand je fais une copy de vecteur de réels avec une simple boucle (les
resultats sont équivalent sur des pointeur C où des vecteurs STL),
j'obtiens des perfs qui sont les mêmes que si je passe par memcpy(..).
Je m'interesse en particulier aux grand vecteur (eg. sizee6).
for (int i=0 , i <size ; i++) X[i]=Y[i]
Sur ma machine, les perfs hors cache sont +/- constantes ( +/- 50
Millions d'élements copiés par seconde)
A ce point, tout va bien et le compilo (gcc) semble faire un boulot
correct...
Sauf que : Si je fais la même opération via ATLAS ( ATL_dcopy(..)),
j'obtiens une performance meilleure d'un facteur 2 (+/- 100 Millions
d'éléments copiés par seconde).
Trois questions :
1 Vous semble-t-il normal qu'une opération aussi élémentaire soit
"nativement" aussi peu optimisée ?
2 Est-il possible de modifier l'environnement pour que la version
boucle soit efficace (modif de la libc ?)
3 Je n'ai rien compris au film ?
P.S. Je développe une bibliothèque où les opérations globale sur
les vecteurs sont définies et sil'utilisateur
écrit X=Y cela appel ATLAS si la lib est installée. Mais j'ai quand
même l'impression que ce bon niveau de perf
devrait être accessible directement depuis le langage...
Quand je fais une copy de vecteur de réels avec une simple boucle (les
resultats sont équivalent sur des pointeur C où des vecteurs STL),
j'obtiens des perfs qui sont les mêmes que si je passe par memcpy(..).
Je m'interesse en particulier aux grand vecteur (eg. sizee6).
for (int i=0 , i <size ; i++) X[i]=Y[i]
Sur ma machine, les perfs hors cache sont +/- constantes ( +/- 50
Millions d'élements copiés par seconde)
A ce point, tout va bien et le compilo (gcc) semble faire un boulot
correct...
Sauf que : Si je fais la même opération via ATLAS ( ATL_dcopy(..)),
j'obtiens une performance meilleure d'un facteur 2 (+/- 100 Millions
d'éléments copiés par seconde).
Trois questions :
1 Vous semble-t-il normal qu'une opération aussi élémentaire soit
"nativement" aussi peu optimisée ?
2 Est-il possible de modifier l'environnement pour que la version
boucle soit efficace (modif de la libc ?)
3 Je n'ai rien compris au film ?
P.S. Je développe une bibliothèque où les opérations globale sur
les vecteurs sont définies et sil'utilisateur
écrit X=Y cela appel ATLAS si la lib est installée. Mais j'ai quand
même l'impression que ce bon niveau de perf
devrait être accessible directement depuis le langage...
Quand je fais une copy de vecteur de réels avec une simple boucle (les
resultats sont équivalent sur des pointeur C où des vecteurs STL),
j'obtiens des perfs qui sont les mêmes que si je passe par memcpy(..).
Je m'interesse en particulier aux grand vecteur (eg. sizee6).
for (int i=0 , i <size ; i++) X[i]=Y[i]
Sur ma machine, les perfs hors cache sont +/- constantes ( +/- 50
Millions d'élements copiés par seconde)
A ce point, tout va bien et le compilo (gcc) semble faire un boulot
correct...
Sauf que : Si je fais la même opération via ATLAS ( ATL_dcopy(..)),
j'obtiens une performance meilleure d'un facteur 2 (+/- 100 Millions
d'éléments copiés par seconde).
Trois questions :
1 Vous semble-t-il normal qu'une opération aussi élémentaire soit
"nativement" aussi peu optimisée ?
2 Est-il possible de modifier l'environnement pour que la version
boucle soit efficace (modif de la libc ?)
3 Je n'ai rien compris au film ?
P.S. Je développe une bibliothèque où les opérations globale sur
les vecteurs sont définies et sil'utilisateur
écrit X=Y cela appel ATLAS si la lib est installée. Mais j'ai quand
même l'impression que ce bon niveau de perf
devrait être accessible directement depuis le langage...
Bonjour à tous,
je viens de faire des mesures de perfs sur mon système linux (X86) qui
me laissent un peu songeur...
Quand je fais une copy de vecteur de réels avec une simple boucle (les
resultats sont équivalent sur des pointeur C où des vecteurs STL),
j'obtiens des perfs qui sont les mêmes que si je passe par memcpy(..).
Je m'interesse en particulier aux grand vecteur (eg. sizee6).
for (int i=0 , i <size ; i++) X[i]=Y[i]
Sur ma machine, les perfs hors cache sont +/- constantes ( +/- 50
Millions d'élements copiés par seconde)
A ce point, tout va bien et le compilo (gcc) semble faire un boulot
correct...
Sauf que : Si je fais la même opération via ATLAS ( ATL_dcopy(..)),
j'obtiens une performance meilleure d'un facteur 2 (+/- 100 Millions
d'éléments copiés par seconde).
Trois questions :
1 Vous semble-t-il normal qu'une opération aussi élémentaire soit
"nativement" aussi peu optimisée ?
2 Est-il possible de modifier l'environnement pour que la version
boucle soit efficace (modif de la libc ?)
Bonjour à tous,
je viens de faire des mesures de perfs sur mon système linux (X86) qui
me laissent un peu songeur...
Quand je fais une copy de vecteur de réels avec une simple boucle (les
resultats sont équivalent sur des pointeur C où des vecteurs STL),
j'obtiens des perfs qui sont les mêmes que si je passe par memcpy(..).
Je m'interesse en particulier aux grand vecteur (eg. sizee6).
for (int i=0 , i <size ; i++) X[i]=Y[i]
Sur ma machine, les perfs hors cache sont +/- constantes ( +/- 50
Millions d'élements copiés par seconde)
A ce point, tout va bien et le compilo (gcc) semble faire un boulot
correct...
Sauf que : Si je fais la même opération via ATLAS ( ATL_dcopy(..)),
j'obtiens une performance meilleure d'un facteur 2 (+/- 100 Millions
d'éléments copiés par seconde).
Trois questions :
1 Vous semble-t-il normal qu'une opération aussi élémentaire soit
"nativement" aussi peu optimisée ?
2 Est-il possible de modifier l'environnement pour que la version
boucle soit efficace (modif de la libc ?)
Bonjour à tous,
je viens de faire des mesures de perfs sur mon système linux (X86) qui
me laissent un peu songeur...
Quand je fais une copy de vecteur de réels avec une simple boucle (les
resultats sont équivalent sur des pointeur C où des vecteurs STL),
j'obtiens des perfs qui sont les mêmes que si je passe par memcpy(..).
Je m'interesse en particulier aux grand vecteur (eg. sizee6).
for (int i=0 , i <size ; i++) X[i]=Y[i]
Sur ma machine, les perfs hors cache sont +/- constantes ( +/- 50
Millions d'élements copiés par seconde)
A ce point, tout va bien et le compilo (gcc) semble faire un boulot
correct...
Sauf que : Si je fais la même opération via ATLAS ( ATL_dcopy(..)),
j'obtiens une performance meilleure d'un facteur 2 (+/- 100 Millions
d'éléments copiés par seconde).
Trois questions :
1 Vous semble-t-il normal qu'une opération aussi élémentaire soit
"nativement" aussi peu optimisée ?
2 Est-il possible de modifier l'environnement pour que la version
boucle soit efficace (modif de la libc ?)
Voila peut-etre ce que ATLAS fait et qui depasse le cadre de la STL.
Voila peut-etre ce que ATLAS fait et qui depasse le cadre de la STL.
Voila peut-etre ce que ATLAS fait et qui depasse le cadre de la STL.
Laurent Deniau wrote:Voila peut-etre ce que ATLAS fait et qui depasse le cadre de la STL.
Je vois pas pourquoi cela dépasserait du cadre.
Une implémentation de la bibliothèque standard n'a pas à être portable.
C'est justement l'intérêt qu'elle soit standard : chaque compilateur
peut écrire la sienne optimisée pour son compilateur.
En fait il est même difficile de distinguer compilateur et bibliothèque
standard, car le moyen le plus performant de l'implémenter et de faire
de cette bibliothèque un élément du compilateur.
Bien sûr quand le compilateur lui-même est portable, c'est assez compliqué.
Laurent Deniau wrote:
Voila peut-etre ce que ATLAS fait et qui depasse le cadre de la STL.
Je vois pas pourquoi cela dépasserait du cadre.
Une implémentation de la bibliothèque standard n'a pas à être portable.
C'est justement l'intérêt qu'elle soit standard : chaque compilateur
peut écrire la sienne optimisée pour son compilateur.
En fait il est même difficile de distinguer compilateur et bibliothèque
standard, car le moyen le plus performant de l'implémenter et de faire
de cette bibliothèque un élément du compilateur.
Bien sûr quand le compilateur lui-même est portable, c'est assez compliqué.
Laurent Deniau wrote:Voila peut-etre ce que ATLAS fait et qui depasse le cadre de la STL.
Je vois pas pourquoi cela dépasserait du cadre.
Une implémentation de la bibliothèque standard n'a pas à être portable.
C'est justement l'intérêt qu'elle soit standard : chaque compilateur
peut écrire la sienne optimisée pour son compilateur.
En fait il est même difficile de distinguer compilateur et bibliothèque
standard, car le moyen le plus performant de l'implémenter et de faire
de cette bibliothèque un élément du compilateur.
Bien sûr quand le compilateur lui-même est portable, c'est assez compliqué.
Une implémentation de la bibliothèque standard n'a pas à être portable.
C'est justement l'intérêt qu'elle soit standard : chaque compilateur
peut écrire la sienne optimisée pour son compilateur.
Une implémentation de la bibliothèque standard n'a pas à être portable.
C'est justement l'intérêt qu'elle soit standard : chaque compilateur
peut écrire la sienne optimisée pour son compilateur.
Une implémentation de la bibliothèque standard n'a pas à être portable.
C'est justement l'intérêt qu'elle soit standard : chaque compilateur
peut écrire la sienne optimisée pour son compilateur.
Merci pour vos réponses. Je suis en train de faire les tests que vous
avez suggérés (std::copy, valarray ?). Je vais aussi voir ce que
donne le compilo intel (et aussi le fortran). En tout état de cause,
et malgré certains avis, mes questions ne me semblent toujours pas
tellement déplacées. En effet, je ne connais rien à la conception
des compilateurs mais je crois toujours que leur rôle est de
transformer, d'une façon aussi efficace que possible, du code source
(écrit par des humains) en langage machine. Étant donné qu'il existe
des outils open-source (e.g. ATLAS) qui fournissent des
implémentations d'opérations élémentaires (je maintiens !)
optimisées pour des machines cible données, il semble à priori
possible d'inclure ces fonctionnalités dans le compilo.
Merci pour vos réponses. Je suis en train de faire les tests que vous
avez suggérés (std::copy, valarray ?). Je vais aussi voir ce que
donne le compilo intel (et aussi le fortran). En tout état de cause,
et malgré certains avis, mes questions ne me semblent toujours pas
tellement déplacées. En effet, je ne connais rien à la conception
des compilateurs mais je crois toujours que leur rôle est de
transformer, d'une façon aussi efficace que possible, du code source
(écrit par des humains) en langage machine. Étant donné qu'il existe
des outils open-source (e.g. ATLAS) qui fournissent des
implémentations d'opérations élémentaires (je maintiens !)
optimisées pour des machines cible données, il semble à priori
possible d'inclure ces fonctionnalités dans le compilo.
Merci pour vos réponses. Je suis en train de faire les tests que vous
avez suggérés (std::copy, valarray ?). Je vais aussi voir ce que
donne le compilo intel (et aussi le fortran). En tout état de cause,
et malgré certains avis, mes questions ne me semblent toujours pas
tellement déplacées. En effet, je ne connais rien à la conception
des compilateurs mais je crois toujours que leur rôle est de
transformer, d'une façon aussi efficace que possible, du code source
(écrit par des humains) en langage machine. Étant donné qu'il existe
des outils open-source (e.g. ATLAS) qui fournissent des
implémentations d'opérations élémentaires (je maintiens !)
optimisées pour des machines cible données, il semble à priori
possible d'inclure ces fonctionnalités dans le compilo.
Merci pour vos réponses. Je suis en train de faire les tests que vous
avez suggérés (std::copy, valarray ?). Je vais aussi voir ce que
donne le compilo intel (et aussi le fortran). En tout état de cause,
et malgré certains avis, mes questions ne me semblent toujours pas
tellement déplacées.
En effet, je ne connais rien à la conception
des compilateurs mais je crois toujours que leur rôle est de
transformer, d'une façon aussi efficace que possible, du code source
(écrit par des humains) en langage machine.
Étant donné qu'il existe
des outils open-source (e.g. ATLAS) qui fournissent des
implémentations d'opérations élémentaires (je maintiens !)
optimisées pour des machines cible données, il semble à priori
possible d'inclure ces fonctionnalités dans le compilo.
De mon propre point de vue, l'inefficacité du compilo est presque un
avantage puisque cela justifie encore plus l'usage de librairies
spécialisées.
Au départ un de mes buts était de fournir des
opération globales (X+=a*Y+b*Z) sur des vecteurs multi-dimentionels
(vecteur<vecteur<..>>) en étendant l'usage des Expression Template
(à la Blitz++) à ce cas. Les implémentations classiques de l'E.T.
(via un CRTP), se fondent sur la définition d'un opérateur [] pour
les expressions qui retourne un résultat du type des éléments de
vecteurs. Mon idée a priori était que cela serait moins efficace que
les versions boucles dans le cas multidimensionnel du fait de la
création d'un élément de vecteur qui se trouve être un vecteur dans
le cas multidimensionnel. Quelle ne fut pas ma surprise de cosntater
que c'était l'inverse et que via ATLAS, j'obtenais des résultats E.T.
supérieurs aux boucles écrites à la main... De là, l'idée de
recoder des expressions vectorielles simples (vecteurs
mono-dimensionnels) en simulant des vecteurs 2D où la taille des
blocks est choisie de façon optimale. A première vue ça marche et
j'ai un gain de perf d'environ 40% sur l'écriture boucle... Avant
cela, je n'avais jamais entendu parler de blocking utile pour des
opérations vecteurs-vecteurs hors cache (seulement pour du
matrice-matrice).
On en apprend tous les jours... ;-)
Merci pour vos réponses. Je suis en train de faire les tests que vous
avez suggérés (std::copy, valarray ?). Je vais aussi voir ce que
donne le compilo intel (et aussi le fortran). En tout état de cause,
et malgré certains avis, mes questions ne me semblent toujours pas
tellement déplacées.
En effet, je ne connais rien à la conception
des compilateurs mais je crois toujours que leur rôle est de
transformer, d'une façon aussi efficace que possible, du code source
(écrit par des humains) en langage machine.
Étant donné qu'il existe
des outils open-source (e.g. ATLAS) qui fournissent des
implémentations d'opérations élémentaires (je maintiens !)
optimisées pour des machines cible données, il semble à priori
possible d'inclure ces fonctionnalités dans le compilo.
De mon propre point de vue, l'inefficacité du compilo est presque un
avantage puisque cela justifie encore plus l'usage de librairies
spécialisées.
Au départ un de mes buts était de fournir des
opération globales (X+=a*Y+b*Z) sur des vecteurs multi-dimentionels
(vecteur<vecteur<..>>) en étendant l'usage des Expression Template
(à la Blitz++) à ce cas. Les implémentations classiques de l'E.T.
(via un CRTP), se fondent sur la définition d'un opérateur [] pour
les expressions qui retourne un résultat du type des éléments de
vecteurs. Mon idée a priori était que cela serait moins efficace que
les versions boucles dans le cas multidimensionnel du fait de la
création d'un élément de vecteur qui se trouve être un vecteur dans
le cas multidimensionnel. Quelle ne fut pas ma surprise de cosntater
que c'était l'inverse et que via ATLAS, j'obtenais des résultats E.T.
supérieurs aux boucles écrites à la main... De là, l'idée de
recoder des expressions vectorielles simples (vecteurs
mono-dimensionnels) en simulant des vecteurs 2D où la taille des
blocks est choisie de façon optimale. A première vue ça marche et
j'ai un gain de perf d'environ 40% sur l'écriture boucle... Avant
cela, je n'avais jamais entendu parler de blocking utile pour des
opérations vecteurs-vecteurs hors cache (seulement pour du
matrice-matrice).
On en apprend tous les jours... ;-)
Merci pour vos réponses. Je suis en train de faire les tests que vous
avez suggérés (std::copy, valarray ?). Je vais aussi voir ce que
donne le compilo intel (et aussi le fortran). En tout état de cause,
et malgré certains avis, mes questions ne me semblent toujours pas
tellement déplacées.
En effet, je ne connais rien à la conception
des compilateurs mais je crois toujours que leur rôle est de
transformer, d'une façon aussi efficace que possible, du code source
(écrit par des humains) en langage machine.
Étant donné qu'il existe
des outils open-source (e.g. ATLAS) qui fournissent des
implémentations d'opérations élémentaires (je maintiens !)
optimisées pour des machines cible données, il semble à priori
possible d'inclure ces fonctionnalités dans le compilo.
De mon propre point de vue, l'inefficacité du compilo est presque un
avantage puisque cela justifie encore plus l'usage de librairies
spécialisées.
Au départ un de mes buts était de fournir des
opération globales (X+=a*Y+b*Z) sur des vecteurs multi-dimentionels
(vecteur<vecteur<..>>) en étendant l'usage des Expression Template
(à la Blitz++) à ce cas. Les implémentations classiques de l'E.T.
(via un CRTP), se fondent sur la définition d'un opérateur [] pour
les expressions qui retourne un résultat du type des éléments de
vecteurs. Mon idée a priori était que cela serait moins efficace que
les versions boucles dans le cas multidimensionnel du fait de la
création d'un élément de vecteur qui se trouve être un vecteur dans
le cas multidimensionnel. Quelle ne fut pas ma surprise de cosntater
que c'était l'inverse et que via ATLAS, j'obtenais des résultats E.T.
supérieurs aux boucles écrites à la main... De là, l'idée de
recoder des expressions vectorielles simples (vecteurs
mono-dimensionnels) en simulant des vecteurs 2D où la taille des
blocks est choisie de façon optimale. A première vue ça marche et
j'ai un gain de perf d'environ 40% sur l'écriture boucle... Avant
cela, je n'avais jamais entendu parler de blocking utile pour des
opérations vecteurs-vecteurs hors cache (seulement pour du
matrice-matrice).
On en apprend tous les jours... ;-)
Sauf que : Si je fais la même opération via ATLAS ( ATL_dcopy(..)),
1 Vous semble-t-il normal qu'une opération aussi élémentaire soit
"nativement" aussi peu optimisée ?
'aussi peu' est peut-etre un peu exagere.
2 Est-il possible de modifier l'environnement pour que la version
boucle soit efficace (modif de la libc ?)
En faisant la meme chose que ATLAS?
Sauf que : Si je fais la même opération via ATLAS ( ATL_dcopy(..)),
1 Vous semble-t-il normal qu'une opération aussi élémentaire soit
"nativement" aussi peu optimisée ?
'aussi peu' est peut-etre un peu exagere.
2 Est-il possible de modifier l'environnement pour que la version
boucle soit efficace (modif de la libc ?)
En faisant la meme chose que ATLAS?
Sauf que : Si je fais la même opération via ATLAS ( ATL_dcopy(..)),
1 Vous semble-t-il normal qu'une opération aussi élémentaire soit
"nativement" aussi peu optimisée ?
'aussi peu' est peut-etre un peu exagere.
2 Est-il possible de modifier l'environnement pour que la version
boucle soit efficace (modif de la libc ?)
En faisant la meme chose que ATLAS?