2015-02-04 15 views
7

W C++, próbuję napisać opakowanie wokół 64-bitowej liczby całkowitej. Oczekuję, że jeśli napisano poprawnie i wszystkie metody zostały wstawione, to takie opakowanie powinno być tak wydajne, jak typ rzeczywisty. Odpowiedź na to question na SO wydaje się zgadzać z moimi oczekiwaniami.Dlaczego VC++ nie może zoptymalizować opakowania całkowitego?

Napisałem ten kod, aby przetestować moje oczekiwania:

class B 
{ 
private: 
    uint64_t _v; 

public: 
    inline B() {}; 
    inline B(uint64_t v) : _v(v) {}; 

    inline B& operator=(B rhs) { _v = rhs._v; return *this; }; 
    inline B& operator+=(B rhs) { _v += rhs._v; return *this; }; 
    inline operator uint64_t() const { return _v; }; 
}; 

int main(int argc, char* argv[]) 
{ 
    typedef uint64_t; 
    //typedef B T; 
    const unsigned int x = 100000000; 

    Utils::CTimer timer; 
    timer.start(); 

    T sum = 0; 
    for (unsigned int i = 0; i < 100; ++i) 
    { 
     for (uint64_t f = 0; f < x; ++f) 
     { 
     sum += f; 
     } 
    } 

    float time = timer.GetSeconds(); 

    cout << sum << endl 
     << time << " seconds" << endl; 

    return 0; 
} 

Kiedy uruchomić to z typedef B T; zamiast typedef uint64_t T podane czasy są konsekwentnie o 10% wolniejsze podczas kompilacji z VC++. W g ++ wydajność jest taka sama, jeśli używam opakowania lub nie.

Ponieważ g ++ robi to, myślę, że nie ma żadnego technicznego powodu, dla którego VC++ nie może zoptymalizować tego poprawnie. Czy jest coś, co mógłbym zrobić, aby go zoptymalizować?

Już próbowałem grać z flagą optymalizacje bez powodzenia

+0

Czy uruchomiłeś kod z Visual Studio lub z konsoli Windows? – jpo38

+0

Nie będę zaskoczony, jeśli g ++ złożył całą pętlę. –

+1

Zanurz się w wygenerowanym zespole! –

Odpowiedz

3

Korzystanie /O2 (zmaksymalizować prędkość), obie alternatywy generować dokładnie takie same montaż przy użyciu programu Visual Studio 2012. Jest to kod, minus czas i wyjście:

00FB1000 push  ebp 
00FB1001 mov   ebp,esp 
00FB1003 and   esp,0FFFFFFF8h 
00FB1006 sub   esp,8 
00FB1009 mov   edx,64h 
00FB100E mov   edi,edi 
00FB1010 xorps  xmm0,xmm0 
00FB1013 movlpd  qword ptr [esp],xmm0 
00FB1018 mov   ecx,dword ptr [esp+4] 
00FB101C mov   eax,dword ptr [esp] 
00FB101F nop 
00FB1020 add   eax,1 
00FB1023 adc   ecx,0 
00FB1026 jne   main+2Fh (0FB102Fh) 
00FB1028 cmp   eax,5F5E100h 
00FB102D jb   main+20h (0FB1020h) 
00FB102F dec   edx 
00FB1030 jne   main+10h (0FB1010h) 
00FB1032 xor   eax,eax 

Zakładam, że zmierzone czasy zmieniają się lub nie zawsze są prawidłowe.

+0

'xmm0'! Rejestry MMX! To * spowodowało * wektoryzację operacji! –

+0

@PanagiotisKanavos Rzeczywiście, rzadki widok powiedziałbym. – Daerst

+1

Nie rzadko tak naprawdę, VC jest przewyższany tylko przez własne kompilatory Intela w równoległym kodowaniu. –

4

Dla przypomnienia, to co g ++ i szczęk ++ jest generowany montaż na -O2 przekłada się (zarówno opakowania i nie bibułki przypadków), modulo części zębate:

sum = 499999995000000000; 
cout << sum << endl; 

Innymi słowy, zoptymalizowane zapętlić się całkowicie. Bez względu na to, jak trudno próbujesz zwektoryzować pętlę, trudno jest pokonać nie zapętlając się w ogóle :)

Powiązane problemy