December 25, 2000
De flesta som har spelat mycket känner till hur bra Quake3:s grafikmotor är jämfört med de flesta andra (BF/BF2 kan nämnas som motpol 😉
Sprang på den här intressanta artikeln om en väldigt optimerad bit kod i Quake3 som ger en insikt i hur optimerad Quake3:s motor är.
July 28, 2003
Intressant nog så fungerar den koden inte med modernare C-kompilatorer (till exempel gcc-4.1). Problemet är de roliga castarna mellan int och float; de följer inte riktigt C-standarden och gcc anser därför att den har rätt att optimera hej vilt. Om man kan assembler kan man titta på en objdump och se att kompilatorn mer eller mindre har slängt bort en massa kod.
#include <stdio.h>
static float invsqrt2(float x)
{
float xhalf = 0.5f * x;
union {
int i;
float f;
} u = { .f = x };
u.i = 0x5f3759df - (u.i >> 1);
x = u.f;
x = x * (1.5f - xhalf * x * x);
return x;
}
static float invsqrt1(float x)
{
float xhalf = 0.5f * x;
int i = *(int*)&x;
i = 0x5f3759df - (i >> 1);
x = *(float*)&i;
x = x * (1.5f - xhalf * x * x);
return x;
}
int main(int argc, char **argv)
{
printf("version 1: 1/sqrt(25) = %fn", invsqrt1(25.0f));
printf("version 2: 1/sqrt(25) = %fn", invsqrt2(25.0f));
}
$ gcc --version
gcc (GCC) 4.1.1
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ gcc -march=athlon64 -msse3 -O3 -o foo foo.c
$ ./foo
version 1: 1/sqrt(25) = 0.000000
version 2: 1/sqrt(25) = 0.199690
March 5, 2002
fackamato@fackamato-desktop:~$ ./invsqrt
version 1: 1/sqrt(25) = 0.199690
version 2: 1/sqrt(25) = 0.199690
fackamato@fackamato-desktop:~$ gcc --version
gcc (GCC) 4.1.2 20060928 (prerelease) (Ubuntu 4.1.1-13ubuntu5)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
fackamato@fackamato-desktop:~$ gcc -march=pentium4 -msse2 -O3 -o invsqrt-p4 invsqrt.c
fackamato@fackamato-desktop:~$ ./invsqrt-p4
version 1: 1/sqrt(25) = 0.199690
version 2: 1/sqrt(25) = 0.199690
Fungerar ju, eller vad gör jag för fel? 🙂
July 28, 2003
Testade lite på jobb-datorn (P4):
$ gcc -O1 -o foo foo.c
$ ./foo
version 1: 1/sqrt(25) = 0.199690
version 2: 1/sqrt(25) = 0.199690
$ gcc -O2 -o foo foo.c
$ ./foo
version 1: 1/sqrt(25) = -0.000043
version 2: 1/sqrt(25) = 0.199690
$ gcc -march=pentium4 -O2 -o foo foo.c
$ ./foo
version 1: 1/sqrt(25) = 0.199690
version 2: 1/sqrt(25) = 0.199690
Som synes krävs för det första optimering påslaget, för det andra, man får ej använda march=pentium4. Kan också säga att samma problem uppstår på t.ex. PPC, så det är inte begränsat till bara x86.
December 25, 2000
Blev tvungen att testa när det blev så mycket diskussion, har en second gen g4 och det fungerar fint här borta. Har lite äldre version av gcc dock. Fungera både med och utan (att specificera vet inte vad den gör automatiskt) optimeringar
$ gcc -mcpu=7450 -O2 -pipe -fsigned-char -maltivec -mabi=altivec -mpowerpc-gfxopt invsqrt.c -o invsqrt
$ ./invsqrt
version 1: 1/sqrt(25) = 0.199690
version 2: 1/sqrt(25) = 0.199690
$ gcc --version
powerpc-apple-darwin8-gcc-4.0.1 (GCC) 4.0.1 (Apple Computer, Inc. build 5341)
Copyright (C) 2005 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ gcc invsqrt.c -o invsqrt
$ ./invsqrt
version 1: 1/sqrt(25) = 0.199690
version 2: 1/sqrt(25) = 0.199690
July 28, 2003
Hmm, ganska skoj det här 🙂 Vet inte vilken version det var som "problemet" dök upp i, men det var nyligen. Här är resultatet från en mac-kub:
$ gcc --version
gcc (GCC) 4.0.3 20060128 (prerelease) (Debian 4.0.2-8)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ gcc -mcpu=7450 -O2 -pipe -fsigned-char -maltivec -mabi=altivec -mpowerpc-gfxopt -o foo foo.c
$ ./foo
version 1: 1/sqrt(25) = 0.000000
version 2: 1/sqrt(25) = 0.199690
$ gcc -o foo foo.c
$ ./foo
version 1: 1/sqrt(25) = 0.199690
version 2: 1/sqrt(25) = 0.199690
Så, fortfarande behövs minst -O2, därutöver verkar det bero på vilken processor man har, samt vilken gcc-version.
1 Guest(s)