Dlaczego GCC? Nie lepiej MSVC?

Test 2 – biblioteka standardowa i nie tylko

W tym teście zostały przetestowane std::cin, std::cout, std::sort i prosta implementacja ROT47. Szkielet kodu – czyli wczytywanie danych – wygląda tak:

W teście 2a i 2b (zob. nazewnictwo w paczce), czyli testy ROT47 oraz std::sort po pętli while dodane są odpowiednie kawałki kodu:

W przypadku testu 2c, czyli testu std::cout, linijkę:

zamieniamy na:

czyli po prostu wypisujemy całą zawartość stringu. Test został wykonany na dwóch przypadkach testowych, z czego pierwszy ważył ok. 657 KiB, a drugi ok. 11.15 MiB – czyli zdecydowanie więcej. Oto one:

GCC vs MSVC - Test 2.1

Dane do przetworzenia ważą ok. 657 KiB.


GCC vs MSVC - Test 2.2

Dane do przetworzenia ważą ok. 11.15 MiB.

Kompilator Wczytywanie danych (std::cin+getline+string) [ms] ROT47 [ms] std::sort [ms] std::cout [ms]
Test 2.1 – dane wejściowe ~657 KiB
MSVC 37 5 24 322
GCC 364 3 42 5
Test 2.2 – dane wejściowe ~11.15 MiB
MSVC 629 68 377 5472
GCC 6174 58 864 80

Hmm, jak widać MSVC pozytywnie nas zaskoczyło. Przy wczytywaniu danych MSVC ma miażdżącą przewagę, jednakże przy wypisywaniu danych – przegrywa z kretesem. W przypadku std::sort jest ok. dwukrotnie szybsze, natomiast przy własnej implementacji ROT47 – GCC jest minimalnie szybszy.
Z powyższych wykresów wolno wyciągnąć kilka wniosków (pisząc, że GCC/MSVC coś robi mam na myśli programy skompilowane nimi):

  • std::cin w wersji MSVC działa ok. 2 razy szybciej niż ten w wersji GCC
  • ROT47 jest ok. 3 razy szybszy w wersji GCC
  • std::sort w bibliotece standardowej GCC jest średnio 3 razy szybszy
  • std::cout ma miażdżącą przewagę w wersji GCC – w tych testach średnio 70-krotną


Wiem, iż takie pojedyncze testowane części nie są zbyt miarodajnym testem, więc postanowiłem uczynić krok dalej. Próbowałem skompilować dotychczasowo mój największy projekt (z czasów gimnazjum :P), ok. 9k+ LoC (wszystkie linie) – Mrowqa Text Coder (zob. „Gry i aplikacje -> Desktopowe”) – jednakże nie udało mi się. Pomijając niektóre sprawy uniemożliwiające kompilację MTC natrafiłem na coś dziwnego (tak, wiem, mój kod, mój błąd, ale MSVC to skompilował):

Ciekawe referencję do czego by zwrócił MSVC, gdyby miał ją wziąć z NULLa… Może kiedyś sprawdzę w ramach nowego wpisu jako ciekawostkę :). Po tym błędzie (i paru innych) odechciało mi się kompilacji MTC przez GCC (defaultowo MTC jest skompilowane przez MSVC). Nadal pozostaje jeden problem – w miarę wiarygodny benchmark, więc postanowiłem…

5 myśli nt. „Dlaczego GCC? Nie lepiej MSVC?

  1. Ze skryptu kompilującego:

    cl /FA %file%.%ext% -o %file%_msvc

    %gcc% -O2 -std=c++11 %file%.%ext% -o %file%_gcc.exe

    Czyli porównywane jest GCC z -O2 oraz MSVC z /O0. Takie porównanie nie ma sensu.

  2. Ten tekst diametralnie zmieni swoją postać, gdy włączysz optymalizacje dla kompilatora MSVC. Obecnie porównujesz kod GCC optymalizowany do kodu MSVC z WYŁĄCZONĄ optymalizacją.

  3. Jeszcze jedno – porównujesz jakość kontenera std:list, a nie jakość optymalizacji kodu przez kompilatory. std::list jest beznadziejny w MSVC, więc… porównujesz dwa różne kody źródłowe i w zasadzie jest to co najwyżej ‚benchmark’ kontenera std::list oraz innych użytych narzędzi. Kiedyś sporo benchmarków robiłem różnych kontenerów i std::list pod VC++ jest na tyle beznadziejny, że należy go stosować tylko i wyłącznie tam, gdzie jest konieczność ‚wstawiania’ danych w środek iterowanej listy.

Dodaj komentarz