Jag sitter och testar att skapa extremt effektiva matematik funktioner i C och vill att alla otimeras vid compile time beroende på input arguments så som vektor storlekar, matrisstorlekar osv.
Så jag testade två sätt att göra detta, ena via #define macro och ena via static inline tex:
#define MIN_FUNKTION(a, b) (a * b)
static inline float min_funktion(float a, float b)
{
return a * b;
}
Det som händer förbryllar mig dock, bådas optimering blir exakt lika dan och jag har testat på väldigt många olika funktioner jag skrivit.
Ska det bli såhär? Får man samma nivå av optimering om man använder #define eller static inline? Någon här som har bra koll på detta?
Varför skulle det INTE bli det? Makron är ju främst ett sätt att få mindre att skriva, optimeringen sker ju i ett rätt sent skede av kompileringen och då har antagligen det där makrot och inline-koden blivit exakt samma tokens i parse-trädet.
Jag förväntade mig inte så stor skillnad då jag vet att båda optimeras under compile time, men att det blev exakt samma förvånade mig.
Just då en define lägger in koden där den används medans en static inline använder ett steg i kompileringen för att göra samma sak.
Såhär i efterhand när man har tänkt lite på hur compilerstrukturen är så kanske det va lite mer självklart, men är fortfarande lite fascinerad.
Det är rätt logiskt som sagt var om man tänker på hur en kompilator fungerar.
Källkod är normalt skriven för att kunna läsas av människor, en kompilator behöver inte lika "städad" kod (se t.ex. obfuscated C). Med andra ord går det att skriva källkod på en massa olika sätt men som ändå genererar exakt samma program.
Det är rätt intressant att låta en kompilator lämna kvar alla mellansteg (inte alla kompilatorer numera som skapar filer för mellanstegen tyvärr) och se vad som händer med koden. Ganska snabbt övergår koden från att vara överskådlig till att bli "alldeles för rörig för att man ska kunna följa den".
Det finns för- och nackdelar med båda sätten att skriva. En fördel med funktionsformen är att det är enklare att använda qualifiers (på pekarargument) som const och restrict vilka kan vara viktiga i optimeringssammanhang.
Det är inte alla kompilatorer som behandlar inline lika. Jag har t.ex. haft problem med senaste intel-kompilatorn ICC som helt enkelt struntar i "static inline" om koden runt omkring är komplicerad, men det är väl kanske snarare ett fel i kompilatorn än något annat.
blueint skrev:Makrot tillåter att kompilatorn optimerar för variabeltyp dessutom. Så en heltals (int) multiplikation lär gå snabbare än en dito flyttal (double).
Det här verkar även åt andra hållet (iom type promotion), som t.ex. i följande exempel:
@gkar, vilken tabbe! Naturligtvis har du rätt. Jag känner däremot inte till något fall då float och double inte är 32 respektive 64 bitar, men de finns säkert.
@blueint poängen är att man i funktionsvarianten inte har något val (const eller inte spelar ingen roll). Man måste specificera vilken typ argumenten ska ha. Eller, är det C++ så behöver man ju inte det heller. Då kan man skriva så här: