[c++] snelheid van aanroepen functies

Pagina: 1
Acties:
  • 180 views sinds 30-01-2008
  • Reageer

  • ruuds
  • Registratie: Maart 2001
  • Laatst online: 04-09 14:08
Hallo,

het gaat hier om een functie uit een spel dat ieder frame wordt aangeroepen om iets te tekenen.

dan neem ik aan dat dit:
code:
1
2
3
4
if(( get_wall(x,y) != 0 ) && ( get_wall(x,y) < 255 ))
{
   // ...
}

langzamer is dan
code:
1
2
3
4
5
result = get_wall(x,y);
if(( result != 0 ) && ( result < 255 ))
{
   // ...
}

of zie ik dat nou verkeerd?
zou dit merkbaar tijdswinst opleveren? (of misschien als die functie 9x wordt aangeroepen wat dan dus gereduceerd wordt naar 1)

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 28-08 12:00

Janoz

Moderator Devschuur®

!litemod

sneller? vast wel, maar of het echt meerkbaar is ligt waarschijnlijk meer aan de implementatie van get_wall. Langzamer is het iig niet dus ik zou gewoon voor de 2e oplossing gaan.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


  • ^Mo^
  • Registratie: Januari 2001
  • Laatst online: 04-11-2025
Hangt er vanaf wat er allemaal in get_wall gebeurd... als het alleen iets teruggeeft aan de hand van een minimale berekening zal het niet zo _heel_ veel uitmaken (wel ietsje), maar als er een hele complexe berekening achter zou zitten, dan win je uiteraard tijd...

"There are 10 kinds of people in the world, those who understand binary and those who don't" | Werkbak specs


  • Juicy
  • Registratie: December 2000
  • Laatst online: 15:07
Welke compiler gebruik je ?

-


  • ruuds
  • Registratie: Maart 2001
  • Laatst online: 04-09 14:08
Microsoft Visual C++ 6 (zonder updates enzo)

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12:35

.oisyn

Moderator Devschuur®

Demotivational Speaker

het is sowieso handig om uitkomsten die je meerdere keren nodig hebt maar 1 keer uit te rekenen

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Juicy
  • Registratie: December 2000
  • Laatst online: 15:07
Als je de volledige enterprise uitvoering zou hebben, dan heb je ook de beschikking over Profiler. Hiermee kun je op functieniveau bekijken waar de meeste processortijd weggetrokken wordt.

-


  • whoami
  • Registratie: December 2000
  • Laatst online: 20:10
Uw 2de oplossing zal misschien wel een beetje sneller zijn (afhankelijk van hoe performant die get_wall functie is), maar ik vind ze ook veel leesbaarder (wat ook belangrijk is).

Je kan ook overwegen om bepaalde functies inline te maken.

https://fgheysels.github.io/


  • RickN
  • Registratie: December 2001
  • Laatst online: 14-06-2025
Ik vermoed dat elke compiler dit tot hetzelfde zal optimaliseren.

He who knows only his own side of the case knows little of that.


  • johnwoo
  • Registratie: Oktober 1999
  • Laatst online: 14:52

johnwoo

3S-GTE

Op woensdag 15 mei 2002 09:54 schreef RickN het volgende:
Ik vermoed dat elke compiler dit tot hetzelfde zal optimaliseren.
Dat denk ik niet; er kunnen factoren zijn waardoor de tweede aanroep een ander resultaat kan geven. In dit geval waarschijnlijk niet, maar wat als de functie bijvoorbeeld een vlaggetje omzet, of afhankelijk is van de tijd? De tweede manier zal dus wel degelijk sneller zijn. Bij enkele aanroepen zal je daar op een PC misschien niet veel van merken, maar als het ieder frame wordt gedaan lijkt me het toch zeker de moeite waard. Ik heb wel eens wat AVR geprogrammeerd, dan probeer je zoveel mogelijk inline te doen :) Veel macro's enzo, want de overhead van function calls is daar wel te merken :)

4200Wp ZO + 840Wp ZW + 1680Wp NW | 14xIQ7+ + 1xDS3-L | MTVenusE | HWP1


  • RickN
  • Registratie: December 2001
  • Laatst online: 14-06-2025
Op woensdag 15 mei 2002 10:02 schreef johnwoo het volgende:

[..]

Dat denk ik niet; er kunnen factoren zijn waardoor de tweede aanroep een ander resultaat kan geven. In dit geval waarschijnlijk niet, maar wat als de functie bijvoorbeeld een vlaggetje omzet, of afhankelijk is van de tijd?
Als dit zo is, dan is de tweede optie niet eens functioneel correct (of iig niet equivalent aan de eerste, het kan natuurlijk zijn dat dat niet erg is). Verder sta je er van versteld wat compilers tegenwoordig kunnen; als die functie geen sideeffects heeft denk ik echt dat ie dat ziet en dus gaat optimaliseren. Overigens is de eerste optie "sneller" als het resultaat van de functie 0 is.

He who knows only his own side of the case knows little of that.


  • whoami
  • Registratie: December 2000
  • Laatst online: 20:10
Op woensdag 15 mei 2002 10:09 schreef RickN het volgende:

[..]

Als dit zo is, dan is de tweede optie niet eens functioneel correct (of iig niet equivalent aan de eerste, het kan natuurlijk zijn dat dat niet erg is). Verder sta je er van versteld wat compilers tegenwoordig kunnen; als die functie geen sideeffects heeft denk ik echt dat ie dat ziet en dus gaat optimaliseren. Overigens is de eerste optie "sneller" als het resultaat van de functie 0 is.
Waarom is die eerste optie sneller als het resultaat van die functie 0 is? Dat zie ik nu niet hoor.
In de eerste optie zal die functie in dat geval slechts 1x uitgevoerd worden, maar in het 2de geval wordt die functie zowieso slechts 1x uitgevoerd, en wordt het 2de gedeelte van de if ( && result < 255) ook niet uitgevoerd.

https://fgheysels.github.io/


  • RickN
  • Registratie: December 2001
  • Laatst online: 14-06-2025
Bij de tweede doe je 1 assignment meer..., namelijk die aan result *D (Note vooral ook dat sneller in mijn post tussen "" stond ;) ) Aan de andere kant is dit iets wat wel vrijwel zeker door de compiler wordt geoptimaliseerd, dus eigenlijk is het idd niet sneller.

He who knows only his own side of the case knows little of that.


Verwijderd

Op woensdag 15 mei 2002 10:09 schreef RickN het volgende:
Verder sta je er van versteld wat compilers tegenwoordig kunnen; als die functie geen sideeffects heeft denk ik echt dat ie dat ziet en dus gaat optimaliseren.
Precies. Als er geen (globale) variabelen met het keyword volatile in die functie get_wall() gebruikt worden, moet een beetje compiler het tot één call optimizen.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12:35

.oisyn

Moderator Devschuur®

Demotivational Speaker

Op woensdag 15 mei 2002 11:44 schreef mietje het volgende:

[..]

Precies. Als er geen (globale) variabelen met het keyword volatile in die functie get_wall() gebruikt worden, moet een beetje compiler het tot één call optimizen.
als je compiler niets weet van de inhoud van de functie (en daarvan is de kans nogal groot, aangezien in verhouding de meeste functies in een andere sourcefile staan), dan valt het dus ook niet te optimisen

sommige compilers ondersteunen speciale specifiers waarmee je aangeeft dat f (x) voor dezelfde waarden van x altijd dezelfde uitkomst geeft (meestal iets in de trand van __pure oid)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Op woensdag 15 mei 2002 12:38 schreef .oisyn het volgende:
als je compiler niets weet van de inhoud van de functie (en daarvan is de kans nogal groot, aangezien in verhouding de meeste functies in een andere sourcefile staan), dan valt het dus ook niet te optimisen
Werkt die compiler dan maar op 1 cpp file tegelijk zonder dat ie ook maar enige info uit andere cpp files gebruikt?? Dat zou dan idd wel vervelend zijn mbt optimalisaties...Nooit zo bij stil gestaan eigenlijk.

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21:30
Op woensdag 15 mei 2002 12:47 schreef hondass50 het volgende:

[..]

Werkt die compiler dan maar op 1 cpp file tegelijk zonder dat ie ook maar enige info uit andere cpp files gebruikt?? Dat zou dan idd wel vervelend zijn mbt optimalisaties...Nooit zo bij stil gestaan eigenlijk.
De compiler wel; die compileert losse .cpp files. De linker kan dus wel optimaliseren over functie grenzen. Bv. de MSVC7 linker doet een global optimalization maar Linux heeft dacht ik nog steeds geen specifieke C++ linker.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12:35

.oisyn

Moderator Devschuur®

Demotivational Speaker

doet de MSVC7 linker ook aanpassingen aan de door de compiler geproduceerde code dan? (behalve de adreswijzigingen uiteraard)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Op woensdag 15 mei 2002 12:38 schreef .oisyn het volgende:
als je compiler niets weet van de inhoud van de functie (en daarvan is de kans nogal groot, aangezien in verhouding de meeste functies in een andere sourcefile staan), dan valt het dus ook niet te optimisen
Veel moderne compilers propageren de attributen van de gebruikte variabelen naar de function-description. Dat wil dus zoveel zeggen dat als je een volatile variabele gebruikt in een functie, meteen de hele functie ook volatile wordt. Een ander voorbeeld is het (non-standaard) attribuut "no_return" dat automatisch aan een functie toegekend word als ze exit() aanroept.

Of deze functie-attributen ook gebruikt wordt voor de optimalisatieslagen van de compiler ligt aan het moment van code-emissie. Als het forward declaraties van functies zijn valt er idd. weinig te optimizen, tenzij je die attributen zelf handmatig aan de functie hangt.

  • TheGhostInc
  • Registratie: November 2000
  • Niet online
Eigenlijk geld altijd:
Meten is weten :)

3 regels code zegt heel weinig, als je echt problemen hebt met snelheid, dan wordt het zoiezo tijd om te gaan kijken naar andere oplossingen. (DirectX oid.)
Als je uitgaat van een leuke Amd of P3 processor of hoger, dan zal zelfs 1.000x een regeltje code meer amper meer uitmaken per seconde.
Je hebt waarschijnlijk een groter probleem bij het op het beeld zetten van de spullen, daar is waarschijnlijk de meeste winst te halen.

(Kijk maar eens als je standaard cout's of printf's gebruikt oid. dan blijkt een loopje met of zonder ineens een hoop verschil te maken)

suc6

  • Korben
  • Registratie: Januari 2001
  • Laatst online: 14-11-2025

Korben

() => {};

Op woensdag 15 mei 2002 10:20 schreef RickN het volgende:
Bij de tweede doe je 1 assignment meer..., namelijk die aan result *D (Note vooral ook dat sneller in mijn post tussen "" stond ;) ) Aan de andere kant is dit iets wat wel vrijwel zeker door de compiler wordt geoptimaliseerd, dus eigenlijk is het idd niet sneller.
Klopt, maar dit is slechts een voorbeeld-vergelijking. Als je het probeert met 15 of-vergelijkingen, is de tweede wel degelijk sneller. Bovendien hoeft de compiler zoiets niet te kunnen optimaliseren. Stel dat de functie een waarde uit een array haalt en dat tussen twee calls de array wordt gewijzigd, dan klopt het 'geoptimaliseerde' resultaat niet meer.

.oisyn: Échte programmeurs haten PHP met een passie. Ben jij soms geen echte programmeur?


  • RickN
  • Registratie: December 2001
  • Laatst online: 14-06-2025
Op woensdag 15 mei 2002 14:40 schreef Xenophage het volgende:

[..]

Stel dat de functie een waarde uit een array haalt en dat tussen twee calls de array wordt gewijzigd, dan klopt het 'geoptimaliseerde' resultaat niet meer.
Nee, maar dan klopt het resultaat van de tweede optie ook niet, zoals ik al eerder in de draad zei, toen iemand met dit argument kwam...........

He who knows only his own side of the case knows little of that.


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21:30
Op woensdag 15 mei 2002 13:29 schreef .oisyn het volgende:
doet de MSVC7 linker ook aanpassingen aan de door de compiler geproduceerde code dan? (behalve de adreswijzigingen uiteraard)
Ja, inlining en register/stack allocatie kan MSVC7 door de linker laten doen. Dus dan heb je 0 functie-call overhead.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21:30
Op woensdag 15 mei 2002 13:45 schreef mietje het volgende:

[..]

Veel moderne compilers propageren de attributen van de gebruikte variabelen naar de function-description. Dat wil dus zoveel zeggen dat als je een volatile variabele gebruikt in een functie, meteen de hele functie ook volatile wordt. Een ander voorbeeld is het (non-standaard) attribuut "no_return" dat automatisch aan een functie toegekend word als ze exit() aanroept.

Of deze functie-attributen ook gebruikt wordt voor de optimalisatieslagen van de compiler ligt aan het moment van code-emissie. Als het forward declaraties van functies zijn valt er idd. weinig te optimizen, tenzij je die attributen zelf handmatig aan de functie hangt.
Onzin. Ik kan er weinig anders van maken.

In C++ zijn vrije functies nooit volatile, en methods dan en slechts dan als ze expliciet het keyword volatile hebben. Gebruik van een volatile variabele maakt een functie nooit volatile.

Het (interne) attribuut no_return toekennen aan een functie die exit() aanroept gaat ook lang niet altijd; alleen als een compiler flow-analysis doet om aan te tonen dat alle paden exit() aanroepen.

Je hebt gelijk als je zegt dat de compiler geen optimalisatie kan doen als deze alleen een declaration heeft ( nou ja, ik denk dat je dat bedoelde met forward declarations. Functies hebben nou eenmaal geen forward declaraties, da's alleen voor classes. ). Maar vervolgens zeg je dan dat er weinig te optimizen is, en dan mis je dus linker optimalisaties.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Primal
  • Registratie: Augustus 2001
  • Laatst online: 07:43
Eigenlijk is het heel simpel ;) . Geval 1 is in alle gevallen altijd langzamer.

1) Het compileren duurt wat langer, omdat de compiler toch 2x door de functie heen zal moeten (met de verdere optimalisatie techniek/whatever nog meer) of in ieder geval een 'approach' moeten maken. Of je het merkt is een 2e, maar het gaat nu even om het principe. En stel nu dat de compiler besluit die 2e aanroep weg te optimaliseren (doubt it => voor argumenten zie eerdere posts van o.a. Oisyn over inhoud van functies => bijv. static variabelen waar in de functie acties mee worden uitgevoerd), dan heeft het compileren toch al wat meer tijd gekost. Nogmaals he, het gaat even om het principe. :)

2) Wordt de functie niet weg geoptimaliseerd, dan is het helemaal klare koek. Er wordt meer code gegenereerd en die zal dus ook uitgevoerd worden. MITS (!!!!) uit de 1e functie aanroep van Getwall een waarde komt ongelijk aan 0!!!!!! Komt er een waarde gelijk aan 0, dan wordt de 2e aanroep niet meer gedaan. En in dat geval zou het dan ook niets uitmaken.

Maar zoals eerder geopperd is het een goede gewoonte om berekende waarden die je vaak gebruikt, 1x uit te laten rekenen en dan verder de variabele gebruiken waarin het resultaat is geplaatst.

Misschien ben ik hier en daar wat vergeten, maar ach er is al veel gezegd in dit topic waar veel waarheid in zit. Zie dit dan ook maar als aanvulling op alle andere goede dingen die gezegd zijn. :)

Ik had ooit eens een quote gelezen van een die-hard programmeur uit eind jaren 80, begin jaren 90. Hij zei: "The fastest code is the code that is never called". En dat vond ik toch wel een mooie :) .

"The fastest code, is the code that is never called."

Pagina: 1