Sida 1 av 1

inline vs macro i C

Postat: 17 september 2013, 13:42:23
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

Re: inline vs macro i C

Postat: 17 september 2013, 13:44:23
av sodjan
Vilken skillnad förvänade du dig?

Re: inline vs macro i C

Postat: 17 september 2013, 13:44:51
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.

Re: inline vs macro i C

Postat: 17 september 2013, 13:59:56
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.

Re: inline vs macro i C

Postat: 17 september 2013, 14:03:18
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))

Re: inline vs macro i C

Postat: 17 september 2013, 14:23:01
av baron3d

Re: inline vs macro i C

Postat: 17 september 2013, 14:53:07
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.

Re: inline vs macro i C

Postat: 17 september 2013, 15:08:01
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".

Re: inline vs macro i C

Postat: 17 september 2013, 15:13:53
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).

Re: inline vs macro i C

Postat: 17 september 2013, 18:55:33
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.

Re: inline vs macro i C

Postat: 17 september 2013, 19:14:41
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

Re: inline vs macro i C

Postat: 17 september 2013, 19:45:15
av Korken
Aha! Man får tracka för all bra information. :tumupp:

Re: inline vs macro i C

Postat: 17 september 2013, 20:21:39
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.

Re: inline vs macro i C

Postat: 17 september 2013, 20:24:43
av blueint
"const float" tvingar variabeltypen.

Re: inline vs macro i C

Postat: 17 september 2013, 21:10:33
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