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

[C++] Optimisation

dnob700
dnob700
Niveau 10
16 mai 2004 à 01:05:07

Salut tout le monde.

Grace en partie a vos conseil, la version C++ de mon logiciel marche ( elle est pas complétement terminé, mais c´est fonctionnel).

Ma nouvelle question est sur l´optimisation :
Il y a dans une boucle un switch avec une grande quantité de test.
A chaque fois on regarde si ca correspond a une constante prédéfinie.

Parmis :

  1. define CNT 12

et
const int8 CNT=12;

Est ce que l´une des méthode est mieux ?
Logiquement la méthode #define devrai être plus rapide c´est ca ?

merci.

Altonfrere
Altonfrere
Niveau 10
16 mai 2004 à 08:56:52

Entre define est const il n´y a aucune différence sur l´exécution mais c´est le préprocesseur qui les gère.

Le GROS avantage des const c´est tout simplement leur typage ( un peu comme la différence entre une macro et une fonction inline). Ce qui veut dire que tu pourras en plus d´avoir le même comportement qu´un define, t´assurer que le typage de tes variables seront respectés.

Ensuite concernant la boucle, le switch est de loin la meilleure solution, et contrairement à ce que tu sembles dire, tu n´effectues pas plus d´un test par boucle, je m´explique :

switch(var)
{
case 1 : . .. ; break;
case 2 : . .. ; break;
. ..
case 100 : . .. ; break;
default : . ...
}

Chaque evaluation de ce switch effectue un branchement " direct" sur la valeur correspondante, l´équivalent avec des if serait :

if ( var == 1)
{
. ..
}
else if ( var == 2)
{
}
. ..
else if ( var == 100)
{
. ..
}
else
{
. ..
}

et là c´est le drame :)

Car si le plus souvent la variable var est égale à 100, tous les if précédent seront évalués et donc perte de temps inutile ! si un jour tu n´as pas le choix d´effecteur des if/else if dans ce genre là, il faut ordonner les comparaison dans l´ordre des plus probables au moins probables, cela limitera le nombre de condition à évaluer . ..

zedix
zedix
Niveau 5
16 mai 2004 à 12:43:09

La meilleure optimisation reste quand même d´utiliser le bon algo. Ensuite, rien ne sert de se casser la tête, car le compilateur optimise souvent bien mieux que nous.

dnob700
dnob700
Niveau 10
16 mai 2004 à 13:26:14

oui et non d´après moi quand même.

par ce que si t´optimise mal ton logiciel, le compilo pourra faire tout ce qu´il veut, le logiciel sera mal optimisé. Car le logiciel ne comprend pas ce que tu veux faire, donc si tu fait quelque chose d´inutiliement compliqué, il ne peut pas savoir que tu voulais faire un truc beaucoup plus simple.

Mais donc, pour ma question, dans le cas des const, le nom de la variable sera lui aussi remplacé à la compilation par sa valeur tout comme un #define.
d´accord, merci beaucoup pour ta réponse altonfrere

Kelios
Kelios
Niveau 8
17 mai 2004 à 00:38:58

" Ensuite, rien ne sert de se casser la tête, car le compilateur optimise souvent bien mieux que nous."
LOL. Et dire que ce n´est pas la première fois que j´entend ça...
Désolé, mais tous les compilos font de l´optimisation qui va du minable au correct. Oui je sais, tu as dit, souvent. Moi je dis, quasiment jamais. Sincèrement, rien ne vaut un humain. Surtout si c´est toi qui a conçu le code: y´a que toi qui sait vraiment ce que tu as derrière la tête, parfaitement. Le compilo doit jongler avec les possibilités d´optimisation possibles avec le language, mais il y a des limites à ses possibilités. Maintenant, la question est jusqu´à quel point aller founiner pour optimiser? Et ce que ça vaut vraiment la peine d´aller optimiser à fond, alors que pendant ce temps il aurait été possible de bien s´avancer dans autre chose?

Pour la réponse d´Aitonfrère:
non, je ne crois pas que le compilo le mettrait en immediate, à moins de vraiment, vraiment savoir ce qu´il fait.

Y´a plusieurs problèmes qui s´affichent, si tu tend à considérer une variable const comme une immediate:
Primo, vu que c´est supposé être une variable, en lecture-seule mais une variable quand même, elle est supposée avoir une adresse alors. Si le compilo le fout immediate, on fout quoi? C,est impossible de résoudre & si a est défini comme const int a; par exemple...
Tu va peut-être me demander, mais à quoi ça peut bien servir, de trouver l´adresse d´une constante, vu que tu n´est pas supposé la modifier? Eh bien on peut s´en servir par exemple dans des calculs arithmétiques de pointeurs, qui n´invoquerait pas la lecture directe de la variable.

Deuxième point, le plus important:
const rend constant une variable du point de vue du C/C++ uniquement, et à la compilation&, en plus. Ça veux dire que n´importe quelle autre entitée extérieure pourrait la modifier, voire même le même programme, mais avec d,autres méthodes. Bien que dans l´idéal on ne doit pas faireça, on doit se prévenir de cette évantualité. C´est hors de portée du compilo que de prévoir que les variables soient constantes en tous points.

Troisième point, on peut avoir à prendre en compte la taille mémoire des variables constantes. par exemple, un programme qui se sert de const pour boucher des trous, de façon à aligner certaines variables en mémoire. Comme bien sur ces trous, on ne veux pas s´en servir, on va les mettres const, au cas où ( sécurité supplémentaire). Ici, dans ce cas, on s´attend à ce que les variables prennent de la place, sinon, on est foutu, tout notre algo est foutu en fait.

Bien sur, ce ne sont pas des cas de tous les jours, mais le compilo doit pouvoir jongler avec tous les cas. Même des cas rares.

Kelios
---------

kufa
kufa
Niveau 9
17 mai 2004 à 04:26:17

Moi je dis, quasiment jamais

Ok, ca depends vraiment des cas.. Tu sais optimiser pour le cache toi? Bon, ok, vc le fais tres mal, mais regarde le compilo d intel..
Le plus important, a mon avis, et de n optimiser les routines qui en ont besoin, ie de sortir un algo optimise a la main, et le preparer pour la couche d optimisation du compilo.

Ensuite, si c´est pour un switch case, la plupart des compilo vont remplacer le const par un immediat, et oui, c´est plus rapide, et non, ca ne pose aucun probleme d´ethique, par rapport aux donnees que tu peux mettre dans le case.

Ensuite non, un static const ne cree pas forcement une entree dans le fichier objet ( y compris dans la section data.ro), par ex si tu optimise pour la taille.

Ensuite, l alignement de memoire n´est pas fait pas l´utilisateur, mais par le compileur, et ce pour une raison toute simple, c´est platform-dependant. D´ou le __packed pour les structures. Donc avoir des consts pour boucher des trous est reellement inutile et dangereux! ; )

Sinon pour en revenir a la question principale, je serai plutot partisant du const lorsqu un define n est pas necessaire ( portee, etc..), mais si tu veux un truc rapide, si tu n as pas trop de tests, tu peux tout faire sans aucun if/switch, en utilisant un tableau de fonctions.

/ kUfa

Altonfrere
Altonfrere
Niveau 10
17 mai 2004 à 11:12:36

" non, je ne crois pas que le compilo le mettrait en immediate, à moins de vraiment, vraiment savoir ce qu´il fait."

Ah et depuis quand un compilateur ne sait-il pas ce qu´il compile ? ! si tu obtiens parfois des warnings, des erreurs ou rien du tout c´est qu´à priori il sait intérpreter ce que tu lui donnes à avaler.
Je te renvoie donc aux specs du C++ ( pour les const), à la définition du switch mais surtout à sa traduction en assembleur . .. un switch n´est qu´un simple aiguillage indexé sur la valeur même de la variable testée. Constante ou #define le résultat sera le même

" Y´a plusieurs problèmes qui s´affichent, si tu tend à considérer une variable const comme une immediate"

cela n´a jamais été le sujet . .. le compilateur sait utiliser la bonne forme au bon moment

" Primo, vu que c´est supposé être une variable, en lecture-seule mais une variable quand même, elle est supposée avoir une adresse alors."

Yep elle a bien une adresse même dans une section data mais read-only ( tu dois pouvoir trouver ca dans des docs assembleur, le détail des sections etc...)

" const rend constant une variable du point de vue du C/C++ uniquement, et à la compilation&, en plus."

ah et depuis quand ? ?? ( cf section data read-only une fois de plus)

" Ça veux dire que n´importe quelle autre entitée extérieure pourrait la modifier, voire même le même programme, mais avec d,autres méthodes."

Je demande à voir ! Si tu as un exemple je suis preneur car là tu toucherais à une grosse faille d´un compilo ou du système je pense :)

Sur ton 3e point :

Il n´a jamais été dit qu´une variable const n´était pas une variable ! !! Simplement, je rappelle le sujet de ce topic tout de même, son comportement dans un switch sera équivalent et aussi rapide qu´un define. That´s all !

dnob700
dnob700
Niveau 10
17 mai 2004 à 15:51:25

kufa : ya un moyen de savoir si le compilo remplace les const par des #define une fois optimisé ou alors ya que la doc pour nous le dire ?

Et un tableau de fonction ? c´est un truc auquel j´avais pensé, mais je n´ais pas la moindre idée de comment faire, donc si quelqu´un peut m´aider, je suis preneur.
Merci d´avance.

kufa
kufa
Niveau 9
17 mai 2004 à 16:53:33

Il ne le remplace pas par un define, mais par une valeur immediate. Tout facile a verifier, regarde le code source asm de sortie..

Sinon pour les tableaux de fonctions, google ; )
http://www.function-pointer.org/ par ex

Si j ai le tps je posterai qqchose la dessus

dnob700
dnob700
Niveau 10
17 mai 2004 à 18:02:39

merci pour ton lien, j´ai cu comment ca marche.

Il y a quelque post, altonfrère disait qu´un switch ne fait qu´un test pour se brancher à la bonne ligne. Mais une fois compilé, je suppose qu´un grand nombre de test est fait,
donc si mon programme lis des octet et selon la valeur de ces octets appelle une fonction. Et si je remplis dans un tableau chaque ´case´ avec l´adresse de la fonction devant être appelé par l´indice de la case. Est ce que ca sera plsu rapide que le switch, ou est ce que le passage par un pointeur va ralentir l´exécution.

Sinon, je vais reprogrammer le truc et faire des tests pour voir.

Altonfrere
Altonfrere
Niveau 10
17 mai 2004 à 18:29:07

ce que tu décris là c´est exactement ce que fais le switch :) à la différence que le switch ne fait pas appel à une fonction ( passage de paramètres etc...) mais un simple jmp ce qui à mon avis est + rapide

kufa
kufa
Niveau 9
17 mai 2004 à 18:46:59

Oui et non. Si toi tu fais un jump par toi meme, le code est plus court ( des adds en moins, et moins de cache miss), sauf si tes valeurs des cases sont vraiment bien choisies. Si tu veux faire des appels sur des methodes membres de ta classe, alors la l´appel direct par jmp sur ta fonction sera plus court et plus rapide que ton switch.

Altonfrere
Altonfrere
Niveau 10
17 mai 2004 à 19:21:35

ok je vois, mais cela ne fonctionne que dans le cas où tu ferais normalement un appel de fonction dans un switch . .. si tes cases ne sont que des séquences d´instructions, alors utiliser des fonctions n´est pas vraiment optimal ( ou alors j´ai pas capté le truc :)

kufa
kufa
Niveau 9
17 mai 2004 à 19:31:55

C´est optimal si vraiment tu veux sauver 1/2 cycles de cpu.. erm.. super utile ; )
Sinon c est aussi utile lorsque dans ton switch tu ne fais qu appeler une fonction..

dnob700
dnob700
Niveau 10
17 mai 2004 à 21:35:43

bon merci tout le monde, je pense que je vais le laisser comme il est ( en fait, pour rendre le code plus lisible, le switch appelle des fonctions, mais qui sont déclaré inline).

j´en suis vers 60-70% de la v1.0 je vous tiendrais au courent de l´avancement du projet.

Kelios
Kelios
Niveau 8
18 mai 2004 à 02:16:45

Bon, je viens seulement resurgir pour réagir à certains posts, même si tu n´as plus de questions dnob.

" cela n´a jamais été le sujet . . . le compilateur sait utiliser la bonne forme au bon moment "
Dommage alors, il y a peut-être eu confusion, je te cite ici plus tôt.
->
" Entre define et const il n´y a aucune différence sur l´exécution mais c´est le préprocesseur qui les gère. "

Je tiens à spécifier certaines choses sur les sections read-only. C´est bien beau, ces sections, mais vous tendez à perdre de vue sur ce point la portabilité. C´est tout à fait variable selon le format d´exécutable. Je connais bien les sections du PE 32 pour avoir travaillé dessus, et oui, je sais que c´est efficace. Mais ce n,est particulier qu´au PE 32! Je ne connais pas bien le Elf, et j´imagine qu´il doit y avoir l´équivalent. Mais je tiens à vous faire remarquer, comme vous avez peut-être déjà remarqué, que cela tient de la compilation, alors que le choix de placer des variables dans une secion particulière tienty du linker. Et dans plusieurs cas ( gcc entres autres), le compilo ne prévoit pas d´avance en quels format ses fichiers objets seront liés.
Il se peut très bien que ça soit lié en un format qui ne possède même pas de sections! Je prend pour exemple mon Kernel qui est lié en format Flat bin, si on peut appeler ça un format ^^. c´est compilé avec gcc, si vous vous demandiez.

" Ensuite, l alignement de memoire n´est pas fait pas l´utilisateur, mais par le compileur, et ce pour une raison toute simple, c´est platform-dependant. D´ou le __packed pour les structures. Donc avoir des consts pour boucher des trous est reellement inutile et dangereux! ; ) "
Ce n´était qu´un cas particulier, pas la peine de tenter de prouver de son malfondisme. De toute façon je tiens à te faire remarquer que _packed est totalement compiler-dependant...

" " Ça veux dire que n´importe quelle autre entitée extérieure pourrait la modifier, voire même le même programme, mais avec d,autres méthodes."

Je demande à voir ! Si tu as un exemple je suis preneur car là tu toucherais à une grosse faille d´un compilo ou du système je pense "
je n´ai malheureusement aucun code à te donner pour l´instant, mais je compte utiliser(possiblement) ce système comme plate-forme inter rings. Je t´explique:
Du côté user, un ensemble de variables const donnant des infos en direct sur diverses infos. C´est facile à accéder, pas d´appels de fonctions nécessaire, et en temps réel. Ça a le mérite d´être sécuritaire du point de vue de l´utilisateur, car les variables lui sont constantes. C´est donc du read-only de son côté.
De mon côté, ( ring 0), c´est des adresses mémoires comme les autres, et c´est donc très efficace pour les modifier rapidement. En fait l´intéret majeur est de couper l´appel de fonctions inter rings, qui est monstreusement lent, mais avec sysenter et sysexit si tu te demandais.

Il existe tout de moins une consolation à mon système. Y´a volatile qui peut résoudre les problèmes des compilos qu ne respectent pas mon point de vue sur les constantes ; ).
Je tiens en dernier lieu à vous faire part de ceci:
http://casteyde.christian.free.fr/cpp/cours/online/x1432.html
Sur le cours de Casteyde. Il s´est basé exclusivement sur la norme, ou plutôt les Draft Papers de l´ISO 14882. À vous de voir si vous lui faites confiance sur ces points, vous n´êtes pas obligé de le croire.

Je cite:
" Il existe également des modificateurs pouvant s´appliquer à une variable pour préciser sa constance :

const : ce mot clé est utilisé pour rendre le contenu d´une variable non modifiable. En quelque sorte, la variable devient ainsi une variable en lecture seule. Attention, une telle variable n´est pas forcément une constante : elle peut être modifiée soit par l´intermédiaire d´un autre identificateur, soit par une entité extérieure au programme ( comme pour les variables volatile). Quand ce mot clé est appliqué à une structure, aucun des champs de la structure n´est accessible en écriture. Bien qu´il puisse paraître étrange de vouloir rendre « constante » une « variable », ce mot clé a une utilité. En particulier, il permet de faire du code plus sûr ; "

Kelios
---------

Kelios
Kelios
Niveau 8
18 mai 2004 à 02:19:21

Hmmm, faudra que je vérifie plus souvent ce que j´écris.... lapsus:
" mais avec sysenter et sysexit si tu te demandais. "
je voulais dire:
" même avec sysenter et sysexit si tu te demandais. "

Kelios
---------

Chris_le_ouf
Chris_le_ouf
Niveau 5
18 mai 2004 à 15:35:15

Altonfrere:
" Ensuite concernant la boucle, le switch est de loin la meilleure solution, et contrairement à ce que tu sembles dire, tu n´effectues pas plus d´un test par boucle, je m´explique :

switch(var)
{
case 1 : . . . ; break;
case 2 : . . . ; break;
. . .
case 100 : . . . ; break;
default : . . ..
}

Chaque evaluation de ce switch effectue un branchement " direct" sur la valeur correspondante, l´équivalent avec des if serait :

if ( var == 1)
{
. . .
}
else if ( var == 2)
{
}
. . .
else if ( var == 100)
{
. . .
}
else
{
. . .
}

et là c´est le drame

Car si le plus souvent la variable var est égale à 100, tous les if précédent seront évalués et donc perte de temps inutile ! si un jour tu n´as pas le choix d´effecteur des if/else if dans ce genre là, il faut ordonner les comparaison dans l´ordre des plus probables au moins probables, cela limitera le nombre de condition à évaluer . "

Ca fait tilter personne ça ? Altonfrere croit qu´il existe une instruction miracle qui aiguille du premier coup sur le bon case, et personne dit rien. Un switch résulte en une cascade de tests tout comme un enchainement de if/else.

kufa
kufa
Niveau 9
18 mai 2004 à 17:54:25

chris_le_ouf: non pas du tout... Regarde le code source asm de sortie, mis a part un ou deux adds ( et parfois un tableau temporaire), ton switch sera remplace par un call sur une sous fonction, directement en prenant la bonne adresse dans un tableau de fonctions.

Par ex un morceau de switch:

mov eax, DWORD PTR _test$[ebp]
mov DWORD PTR tv64[ebp], eax
mov ecx, DWORD PTR tv64[ebp]
add ecx, 5
mov DWORD PTR tv64[ebp], ecx
cmp DWORD PTR tv64[ebp], 35 ; 00000023H
ja SHORT $L798
mov edx, DWORD PTR tv64[ebp]
movzx eax, BYTE PTR $L835[edx]
jmp DWORD PTR $L837[eax*4] ; appel

Et ce sur la plupart des compilos. Plus les valeurs des cases sont proches et lineaires, plus ya de break, plus c est court. Un seul cmp ici alors que mes valeurs etaient bien differentes.

Altonfrere
Altonfrere
Niveau 10
18 mai 2004 à 19:14:08

" Altonfrere croit qu´il existe une instruction miracle qui aiguille du premier coup sur le bon case, et personne dit rien"

Et oui c´est magique l´informatique :) c´est justement l´intéret d´un switch !

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