CONNEXION
  • RetourJeux
    • Sorties
    • Hit Parade
    • Les + populaires
    • Les + attendus
    • Soluces
    • Tous les Jeux
    • Gaming
  • RetourActu Gaming
    • News
    • Astuces
    • Tests
    • Previews
    • Toute l'actu gaming
  • RetourBons plans
    • Bons plans
    • Bons plans Smartphone
    • Bons plans Hardware
    • Bons plans Image et Son
    • Bons plans Amazon
    • Bons plans Cdiscount
    • Bons plans Decathlon
    • Bons plans Fnac
    • Tous les Bons plans
  • RetourJVTech
    • Actus High-Tech
    • Intelligence Artificielle
    • Smartphones
    • Mobilité urbaine
    • Hardware
    • Image et son
    • Tutoriels
    • Tests produits High-Tech
    • Guides d'achat High-Tech
    • JVTech
  • RetourCulture
    • Actus Culture
    • Culture
  • RetourVidéos
    • A la une
    • Gaming Live
    • Vidéos Tests
    • Vidéos Previews
    • Gameplay
    • Trailers
    • Chroniques
    • Replay Web TV
    • Toutes les vidéos
  • RetourForums
    • Hardware PC
    • PS5
    • Switch 2
    • Xbox Series
    • Switch
    • Pokemon pocket
    • FC 25 Ultimate Team
    • League of Legends
    • Tous les Forums
  • PC
  • PS5
  • Xbox Series
  • Switch 2
  • PS4
  • One
  • Switch
  • iOS
  • Android
  • MMO
  • RPG
  • FPS
En ce moment Genshin Impact Valhalla Breath of the wild Animal Crossing GTA 5 Red dead 2
Liste des sujets

[optimisation c++]fonctionnement du comp

Lagrangien
Lagrangien
Niveau 8
07 mai 2012 à 13:09:40

du compilateur.

Bonjour,

Je suis débutant en programmation et je me pose quelques questions. Imaginons que j'aie besoin, pour la simulation d'un phénomène physique, d'un programme très simple, cependant réitéré un trèèès grand nombre de fois. J'ai des questions par rapport à son optimisation, car j'ignore comment marche un compilateur. Je vais donc poster un code, puis des idées de variantes. Pourriez-vous me dire si une des variantes est préférables ? Ou si mon code est nul sur le principe?

Code :

int a,b;
int c[tres_tres_gros_nombre]; // tableau d'entiers

for(int i=0;i<=tres_tres_gros_nombre-1;i++)
{

a = (formule qui depend de i...);
b = (autre formule...);

c[i] = a/b ;

}

Variante 1 :

si dans la boucle, je mets directement :

c[i] = (formule qui depend de i...) / (autre formule...) ;

c'est à dire que je ne passe pas par le calcul de a et b. J'imagine que le programme sera plus rapide ?

Variante 2 : si à la place de (formule qui depend de i...) et (autre formule...) je met f(i) et g(i), deux fonctions qui seraient déclarées et définies en amont du programme (et qui font le même calcul), ça serait moins rapide?

Enfin, toute dernière question, qui n'a pas grand chose à voir.

float a = 1;
float b = 10;
float c = a/b;
cout >> c; // cela m'affiche 0.1

------------------

float a = 1/10;
cout >> c; // cela m'affiche 0

Pourquoi? :-(

Merci infiniment chers forumeurs

tbop2
tbop2
Niveau 10
07 mai 2012 à 13:47:37

Variante 1:

Ce sera un chouilla (comment ca s'ecrit cette bete la) plus rapide. Apres l'optimisation c'est toujours le probleme, ca doit toujours partir d'une necessite mesuree et on n'optimise pas si le cas ne se presente pas dans la vie concrete, on garde un code propre, lisible, comprehensible avec des algorithmes naifs s'il le faut.
Honnetement sans avoir plus de renseignements sur les deux formules c'est impossible a estimer de maniere concrete cependant (c'est d'ailleurs tres difficile a estimer dans les chiffres, c'est pour ca qu'on mesure avant toute chose pour ce petit genre d'optimisation quasi non-algorithmique).
Generalement la complexite d'un algorithme c'est surtout le nombre d'operations derriere. Dans un tel cas concret dans ce sont les forumules qu'il faut optimiser. Par exemple pourquoi recalculer l'autre formule si celle-ci ne depend ni de a ni de i ? Autant ne la calculer qu'une seule fois dans tous le programme non ?

Variante 2 :
Oui ca sera un chouilla plus long, encore une fois tout cela est tres difficilement predictible meme dans l'exemple concret, les compilateurs font moultes optimisations, et il y a plusieurs compilateurs. Tout ca se mesure dans le cas concret et tu en tires les conclusions si oui ou non il y a besoin d*ameliorer le programme.

float c = a/b; // On divise a et b deux floats, le resultat de la division donne un float

float a = 1/10; // On divise deux entiers, le resultat d'une division entiere donne un resultat entier qui sera ensuite affecte et caste en tant que float, la precision flottante est cependant deja perdue entre les deux instructions. La solution a ton probleme est de remplacer 10 par 10.f ou 10.0 par exemple.

hyrulink2
hyrulink2
Niveau 7
07 mai 2012 à 13:55:56

Variante 1:
Normalement il n'y a pas de raison que le programme soit plus rapide. En gros, quand tu fait:
c = expr1 / expr2
le compilateur transforme ça en quelque chose qui ressemble à ça:
c = expr1;
tmp = expr2;
c /= tmp;
Pourquoi? En fait le compilateur transforme ton code C++ en code assembleur, et en assembleur il est impossible de faire des choses comme c = expr1 / expr2, il va donc decomposer tes calculs. Resultat, les deux versions devraient être aussi rapide(mais dans tout les cas ça dépend du compilateur et de son implémentation).

Variante 2:
La encore ce n'est pas sûr que cette variante soit plus rapide si tu est en C99 ou C++.
En effet si les fonctions sont appelées ça sera plus lent mais sous certaines conditions le compilateur peut décider de remplacer l'appel des fonctions par leur code pour rendre le programme plus rapide (inliner les fonctions).
Tu peut plus l'inciter à faire l'inlining en déclarant la fonction inline:
inline int f(int a)
{
...
}
par contre il faut mettre le code dans le .h.
Mais ça ne veut pas dire qu'elle sera inlinée. Il existe des moyens non standard de lui forcer la main mais je te laisse chercher...

Dernière question:
1/10 est une division entière donc tu doit mettre l'une des opérandes en flottant pour que ça marche:
1.0/10 fonctionne car le .0 transforme le 1 en nombre flottant(à virgule).

041
041
Niveau 10
07 mai 2012 à 15:36:19

Aucune de tes deux variantes n'améliorera sensiblement la vitesse.

La seule solution est de minimiser le nombre d'opérations dans la boucle, et ça tu le fait en simplifiant mathématiquement.

Tu dois donc écrire (formule qui depend de i...)/(autre formule...) sur papier et voir si tu peux simplifie la formule ou la présenter sous une autre forme.

Ca peut être intéressant d'essayer de la passer sous une autre forme quand on sait que la division est une opération bien plus longue que + - *.

Sans avoir les formules, difficile de t'aider plus.

godrik
godrik
Niveau 30
07 mai 2012 à 18:25:12

Aucune des formes ne changera la vitesse d'execution a moins que le calcul de f et g soit tres rapide auquel cas l'appel de fonction a f et g ajoutera un temps additionnel mesurable.

Je tiens a noter que le conseil de tbop2 est souvent valide dans le cas general. mais, dans mon experience personnelle, les codes des physiciens sont des cas particulier. Compte tenu de ta question, j'imagine que c'est un code que tu ecris pour tes etudes. Mais de facon generale, les codes de simulation physiques sont souvent amene a tourner sur des super calculateurs dont le cout de maintenance (ne parlons pas du cout d'achat) est largement superieur a ton salaire annuel. Dans un tel context, souvent toutes les optimisations comptent.

Lagrangien
Lagrangien
Niveau 8
07 mai 2012 à 19:17:15

Ok merci pour vos réponses, c'est plus clair.

De toute manière c'est clair que je simplifie les expressions mathématiques "à la main" avant de les utiliser dans le code.

Et sinon pour le reste ben je vais continuer à faire un code clair et net si ça rallonges pas tant que ça le temps de calcul.

kufa
kufa
Niveau 9
08 mai 2012 à 00:42:32

Il y a bcp trop de facteurs pour pouvoir dire quelle solution sera la plus rapide: le compilo utilise, le niveau d'optimisation du compilo, target platform, etc.
Par exemple, rien ne dit que la variante 2 ne puisse pas etre plus rapide si le compilo decide de ne pas inliner une des deux fonctions pour etre sur que ta boucle tienne dans l'instruction cache, etc. Reciproquement, la variante 1 peut aboutir a une meilleure reorganisation des instructions, etc.

De maniere generale il faut plus se concentrer sur les algos que sur les details de possibles optimisations du compilo, qui fait souvent du bon boulot; au besoin, on peut tjs analyzer le code produit ou faire tourner vtune/pix/etc.

Je conseil souvent de ne pas faire de functions trop grosses (reutilisation, possible inline, petite utilisation cache, plus facile a optimiser, le compilo a (souvent) plus de possiblitees pour l'optimiser), et dans ton cas bien precis, j'opterai perso pour la variante 2, en mettant f et g inline.

/k

Sous forums
  • Aide à l'achat Mac
  • Création de sites web
  • Création de Jeux
  • Linux
  • Programmation
  • Internet
  • Steam Deck
  • Macintosh
  • Hardware
La vidéo du moment