32/64 bites programban int/long műveletek

Előzmény.

tl;dr: kiváncsi voltam, hogy hogy viszonyul egy 64 bites gépen az int és long összeadás sebessége különböző CPU-k között attól függően, hogy 32 vagy 64 bitesként van futtatva. Annyi időm nem volt, hogy C++-ban is mérjem, most csak .NET 4-el, debug profileban mértem, ill arra se volt nagyon időm megnézni, hogy milyen ASM kódra fordul, de ez jött ki:

Core 2 Dup E6550, W7x64:

32 bit:
int:  00:00:03.2994532
long: 00:00:04.5314806

64 bit:
int:  00:00:04.6926384
long: 00:00:04.6486878

Xeon E5520, WS2012r2/Xen 6.2:

32 bit:
int:  00:00:03.3697765
long: 00:00:04.2228463

64 bit:
int:  00:00:04.6395212
long: 00:00:04.6332392

Xeon E5-2620v2, WS2012r2/Xeon 6.2:

32 bit:
int:  00:00:04.0602863
long: 00:00:04.1566182

64 bit: 
int:  00:00:04.1773163
long: 00:00:03.9401872

Tesztkód (Unsafe módot be kell neki nyomni, különben a sizeof(int*) nem fog menni):

class Program
    {
        static unsafe void Main(string[] args)
        {
            Console.WriteLine("sizeof(int*) = {0}, Environment.Is64BitProcess = {1}",
                sizeof(int*),
                Environment.Is64BitProcess);

            var sw = Stopwatch.StartNew();

            for (int i = 0; i < 100000; i++)
            {
                int a = 0; int b = 1;
                for (int j = 0; j < 10000; j++) a = a + b;
            }

            sw.Stop();

            Console.WriteLine("int:  {0}", sw.Elapsed);

            sw.Restart();

            for (int i = 0; i < 100000; i++)
            {
                long a = 0; long b = 1;
                for (int j = 0; j < 10000; j++) a = a + b;
            }

            sw.Stop();

            Console.WriteLine("long: {0}", sw.Elapsed);
            Console.ReadLine();

        }
    }

Lefordított binárisok, ha esetleg valaki még mérni akar:

http://shared.muportal.hu/x86_64/

Hozzászólások

Megkérdezhetem, hogy miért C#-ban írtad?

Biztos vagy abban, hogy a JIT a long-ot 64 bites architektúrán 64 bitesre fordítja és nem 32 bites összeadások/szorzások összegére?

Ennek a mérésnek így sok értelme nincs.

debug profileban mértem, ill arra se volt nagyon időm megnézni, hogy milyen ASM kódra fordul, de ez jött ki:

Kaptunk egy végeredményt, anélkül, hogy a leghalványabb fogalmunk lenne arról, hogy mit mértünk. Örülünk neki, ettől most boldogok vagyunk, mert tudjuk hogy a fenti kód az általa használt 4 gépen milyen gyorsan fut le.

Ennél több a tesztekből nem derül ki.

"Megkérdezhetem, hogy miért C#-ban írtad?"

Mert ez volt kéznél.

"Biztos vagy abban, hogy a JIT a long-ot 64 bites architektúrán 64 bitesre fordítja és nem 32 bites összeadások/szorzások összegére?"

Miután debug mód, elég kevés dolgot optimalizál rajta.

De a kedvedért:


                int a = 0; int b = 1;
000000dd  mov         dword ptr [rbp+000000A0h],0 
000000e7  mov         dword ptr [rbp+0000009Ch],1 
[...]
000000fd  nop 
                    a = a + b;
000000fe  mov         ecx,dword ptr [rbp+000000A0h] 
00000104  mov         eax,dword ptr [rbp+0000009Ch] 
0000010a  add         eax,ecx 
0000010c  mov         dword ptr [rbp+000000A0h],eax 

Illetve:


                long a = 0; long b = 1;
00000208  mov         qword ptr [rbp+00000090h],0 
00000213  mov         qword ptr [rbp+00000088h],1 
[...]
                    a = a + b;
0000022b  mov         rcx,qword ptr [rbp+00000090h] 
00000232  mov         rax,qword ptr [rbp+00000088h] 
00000239  add         rax,rcx 
0000023c  mov         qword ptr [rbp+00000090h],rax 

----------------
Lvl86 Troll, "hobbifejlesztő" - Think Wishfully™

Ha most arra vagyunk kiváncsiak, hogy x vagy y a több, akkor igazából mindegy, hogy x,y-t vagy (a+x),(a+y) -t hasonlítünk össze.

Egyébként nem tudom miért gondol mindenki annyi feketemágiát a JIT-terektől, egyrészt negyed annyi dolgot csinálnak meg, mint amit papíron csinálhatnának, másrészt, ha valami tényleg szétszedi a kódot, mint a huzat, az egy régóta fejlesztett C/C++ fordító tele optimalizációs technikákkal.

----------------
Lvl86 Troll, "hobbifejlesztő" - Think Wishfully™

Semmi bajom a JIT-tel, a java-nál jobban csinálja.

Csak tudni kell, hogy mit mérsz. Ahogy a doksit olvastam, ugyanaz a kód másra fordul 32 bites és 64 bites gépen.

C#-pal kapcsolatban már többször kifejtettem, hogy nem a nyelvvel van a bajom, hanem a Microsofttal. Meg kicsit zavar, hogy mindent nagybetűvel írnak, a camelCase-hez szoktam, de ez részlet kérdés.

Nyugodtan használnám a C#-ot fejlesztésre, ha nem futottam volna problémák tömkelegébe, amikor hordozható UI-t akartam írni.

Mit szerettél volna végülis mérni?
Itt a long és int összeadás mellett elég sok "szemét" is van. A for ciklus miatt pl. van 2*100000*10000 int összeadás (i és j increment) amellé, amit elvileg mérni akarsz. Nem lett volna célszerűbb akkor már generálni valami kódot, amiben ki vannak bontva a for ciklusok?