inline vs macro i C

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
Korken
Inlägg: 2230
Blev medlem: 3 februari 2006, 19:19:36
Ort: Luleå, Porsön

inline vs macro i C

Inlägg av Korken »

Godagens!

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:

Kod: Markera allt

#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? :humm:

//Emil
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: inline vs macro i C

Inlägg av sodjan »

Vilken skillnad förvänade du dig?
Nerre
Inlägg: 27230
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Re: inline vs macro i C

Inlägg av Nerre »

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.
Användarvisningsbild
Korken
Inlägg: 2230
Blev medlem: 3 februari 2006, 19:19:36
Ort: Luleå, Porsön

Re: inline vs macro i C

Inlägg av Korken »

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.
Användarvisningsbild
bit96
Inlägg: 2529
Blev medlem: 3 september 2007, 10:04:29
Ort: Säffle

Re: inline vs macro i C

Inlägg av bit96 »

Det hör visserligen inte riktigt till frågeställningen, men man bör använda parenteser runt sina argument i en #define.

Kod: Markera allt

#define MIN_FUNKTION(a, b) ((a) * (b))
Användarvisningsbild
baron3d
EF Sponsor
Inlägg: 1353
Blev medlem: 1 oktober 2005, 23:58:43
Ort: Torestorp

Re: inline vs macro i C

Inlägg av baron3d »

Användarvisningsbild
Icecap
Inlägg: 26650
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: inline vs macro i C

Inlägg av Icecap »

Inline används för minimala kodstumper där ett anrop med stack-placering av variabler "kostar för mycket".

Jag är inte allt förvånat över att slutresultatet blev som du beskrev, det tyder på en rimligt bra kompiler bara.
Nerre
Inlägg: 27230
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Re: inline vs macro i C

Inlägg av Nerre »

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".
blueint
Inlägg: 23238
Blev medlem: 4 juli 2006, 19:26:11
Kontakt:

Re: inline vs macro i C

Inlägg av blueint »

Makrot tillåter att kompilatorn optimerar för variabeltyp dessutom. Så en heltals (int) multiplikation lär gå snabbare än en dito flyttal (double).
superx
Inlägg: 1127
Blev medlem: 19 juni 2012, 23:28:16
Ort: Linköping

Re: inline vs macro i C

Inlägg av superx »

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.
superx
Inlägg: 1127
Blev medlem: 19 juni 2012, 23:28:16
Ort: Linköping

Re: inline vs macro i C

Inlägg av superx »

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:

Kod: Markera allt

extern double getPi();

#define MULTIPLY(a,b) 1.0f/((a)*(b))

static inline float multiply(const float a, const float b)
{
  return 1.0f/(a*b);
}

float test1()
{
  return MULTIPLY(1.23f, getPi());
}

float test2()
{
  return multiply(1.23f, getPi());
}
test1 blir en 64-bitarsdivision
test2 blir en 32-bitarsdivision
Användarvisningsbild
Korken
Inlägg: 2230
Blev medlem: 3 februari 2006, 19:19:36
Ort: Luleå, Porsön

Re: inline vs macro i C

Inlägg av Korken »

Aha! Man får tracka för all bra information. :tumupp:
gkar
Inlägg: 1585
Blev medlem: 31 oktober 2011, 15:28:29
Ort: Linköping

Re: inline vs macro i C

Inlägg av gkar »

@superx, Snyggt exempel, men om vi skall vara hårda; det är inte säkert att det är 32 och 64 bitars division.

Vi känner inte storlekarna på float och double.
Men vi vet att en double ryms i en float.
blueint
Inlägg: 23238
Blev medlem: 4 juli 2006, 19:26:11
Kontakt:

Re: inline vs macro i C

Inlägg av blueint »

"const float" tvingar variabeltypen.
superx
Inlägg: 1127
Blev medlem: 19 juni 2012, 23:28:16
Ort: Linköping

Re: inline vs macro i C

Inlägg av superx »

@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:

Kod: Markera allt

extern double getPi();

#define MULTIPLY(a,b) 1.0f/((a)*(b))

template <typename T>
static inline T multiply(float a, T b)
{
  return 1.0f/(a*b);
}

float test1()
{
  return MULTIPLY(1.23f, getPi());
}

float test2()
{
  return multiply(1.23f, getPi());
}
Då blir det double-division (vilket med min kompilator utförs med 64 bitar) i båda fallen :D
Skriv svar