Programowanie współbieżne, Języki programowania, Aplikacje, Gry

CPU vs GPU: GFLOPS

Styczeń 22nd, 2010 Marcin Borowiec

Czytając różne informacje o kartach graficznych możemy się dowiedzieć, że ich wydajność jest wielokrotnie większa od odpowiednich im cenowo procesorów x86. Często można też zobaczyć liczby w postaci nawet ponad 2TFLOPSów dla GPU i maksymalnie 100GFLOPS dla najszybszych CPU. Dzisiaj postaram się opowiedzieć o teoretycznej wydajności różnych układów i tego w jaki sposób można ją obliczyć. Natomiast w kolejnych postach opisze różnice w architekturze CPU i GPU AMD i NVidii i to jak wpływają one na poziom wykorzystania teoretycznej wydajności.

Zanim jednak przejdę do sedna sprawy muszę napisać pewne uaktualnienie do mojego poprzedniego posta o podstawach GPU. Po jego publikacji AMD wydało w końcu sterowniki (Catalyst 9.12 Hotfix) z obsługą DirectCompute 4.1 dla Radeonów 48xx i 47xx. Niestety część osób będzie zawiedziona. Nadal brakuje obsługi DirectCompute w Radeonach 46xx i słabszych, które również były często kupowane. Podobnie lista rozszerzeń OpenCL dla mojego Radeona 4850 jest ciągle pusta. Pisząc o podstawach GPU pominąłem także jedną ale do niektórych zastosowań ważną rzecz. Radeony 47xx, 48xx, 58xx posiadają obsługę obliczeń na liczbach podwójnej precyzji. NVidia z kolei podwójną precyzje posiada tylko w układach opartych na GT200 i jej implementacja jest dość wolna. Dokładniejsze liczby podam w dalszej części postu.

Na początku postu wspomniałem o FLOPSach i myślę że warto napisać najpierw co to jest. Dość dobrą definicje można przeczytać na wikipedii: http://pl.wikipedia.org/wiki/FLOPS. Jednak na powyższej stronie nie ma wyraźnie zaznaczonej jednej sprawy. Wydajność we FLOPS jednej i tej samej maszyny może dotyczyć różnych rzeczy: (i mieć w zależności od tego inną wartość)

  1. Teoretycznej wydajności wszystkich jednostek obliczeniowych opierając się przede wszystkim na operacjach dodawania i mnożenia bez takich operacji jak np. shift.
  2. Wydajności, która została uzyskana w określonym benchmarku. Taka wydajność będzie przeważnie niższa od wartości z pkt1 w związku z np czekaniem na pobranie danych z pamięci, niemożnością wykorzystania specyficznych jednostek przystosowanych tylko do pewnych operacji czy niemożliwością równoległego wykorzystania kilku jednostek z powodu zależnych od siebie operacji. Podobnie jak w poprzednim przypadku liczone są operacje dodawania i mnożenia wykonywane przez benchmark.

Opisywanie teoretycznej wydajności zaczne od dzisiejszych najmocniejszych jednostek CPU. Weźmy dla przykładu czterordzeniowy Core i7. Każdy z rdzeni posiada jedną jednostkę odpowiedzialną za dodawanie na 128bitowych danych i jedną jednostke do mnożenia na 128bitowych danych co oznacza mniej więcej maksymalnie:

  • 2 operacje x87 na rozszerzonych 80bitowych liczbach zmiennoprzecinkowych w jednym cyklu zegara
  • 4 operacje SSE na 64bitowych liczbach zmiennoprzecinkowych (podwójna precyzja) w jednym cyklu zegara
  • 8 operacji SSE na 32bitowych liczbach zmiennoprzecinkowych (pojedyncza precyzja) w jednym cyklu zegara

Co dla czterordzeniowego Core i7 o taktowaniu 3GHz oznacza wydajność odpowiednio 24GFlops, 48GFlops, 96GFlops dla danego typu operacji czyli całkiem sporo.

Dalej mamy np układ GeForce GTX 280. Do dyspozycji mamy tutaj 30 multiprocesorów, z których każdy posiada 8 jednostek SP (Shader Processor) o wydajności 2 operacje pojedynczej precyzji (jedna operacja mad czyli jedna operacja mnożenia i jedna dodawania (a*b+c)) na jeden cykl i dodatkowo 2 jednostki SFU (Special Function Unit), każda o wydajności 1 operacja specjalna (sin, log, sqrt) lub 4 operacje mnożenia na cykl (dzięki tzw. ‚dual issue’). Razem daje to 30*(8*2 + 2*4) = 720 operacji na jeden cykl dla całego GPU. Mnożąc to przez częstotliwość „szaderów” czyli 1296MHz otrzymujemy 933GFLOPS!

Niestety wydajność tego samego układu w podwójnej precyzji jest znacznie mniejsza. Każdy multiprocesor potrafi wykonać tylko jedną operacje MAD (liczoną jako dwie operacje).  Jednostki SFU nie operują w ogóle na 64bitowych liczbach zmiennoprzecinkowych. Co przekłada się na „tylko” 30*2 = 60 operacji na jeden cykl. Przy częstotliwości 1296MHz daje to ok 78GFlops.

Konkurencyjny Radeon 4870 wydany w podobnym czasie co GTX280 posiada 160 SP pogrupowanych po 16SP w jednym SIMD Engine. Każdy shader składa się z 5 jednostek SPu potrafiących wykonać jedną operacje mad na cykl (także liczone jako 2 operacje na cykl). Dodatkowo jedna z tych 5 jednostek potrafi wykonać jedną instrukcję specjalną na cykl (zamiast instrukcji mad). Razem daje to 10 * 16 * 5 * 2 = 1600 operacji na cykl czyli 1.2TFlops przy częstotliwości 750MHz. Jak widać teoretyczna wydajność Radeona 4870 jest większa niż GeForca GTX280.

W przypadku podwójnej precyzji przewaga Radeona znacznie się zwiększa, gdyż każdy SP potrafi wykonać jedną instrukcje MAD na cykl co daje 10*16*2=320 operacji na cykl co przekłada się na 240GFlops. Ponad 3x więcej niż GTX280! O ile w przypadku pojedynczej precyzji GeForce „nadrabia architekturą” i w wielu przypadkach jest szybszy od Radeona to w double precision trzeba uznać wyższość Radeona. Od razu jednak przypomnę że, aby wydobyć pełnię mocy Radeona trzeba wykorzystać niezbyt wygodny CAL.

Najnowszy Radeon 5870 z punktu widzenia dzisiejszego tematu postu jest podwojonym Radeonem 4870 (zamiast 10 SIMD Engine mamy ich 20) co oznacza 3200 operacji na cykl dla pojedynczej precyzji i 640 operacji dla podwójnej precyzji. Przy zwiększonym taktowaniu rdzenia do 850MHz otrzymujemy 2.72TFlops dla pojedynczej precyzji i 544GFlops dla podwójnej.

Niestety ciągle nie wiadomo jakie parametry będzie miał zapowiadany układ GF100 od NVidii. Brakuje informacji o częstotliwości rdzeni i dokładniejszych informacji o jednostkach SFU. Można jednak spodziewać się wyraźnie wyższej wydajności od Radeona 5870 w podwójnej precyzji i wyraźnie niższej wydajności w pojedynczej precyzji.

Na koniec warto przypomnieć że teoretyczna maksymalna wydajność to nie wszystko. Układy CPU mimo iż teoretycznie wielokrotnie wolniejsze od GPU w wielu zastosowaniach są niezastępowalne. Podobnie Radeon 4870 teoretycznie szybszy od GeForca GTX 280 przegrywa z nim w prawie każdej grze. W kolejnych postach postaram się opisać różnice w architekturze, które decydują o wydajności w realnych zastosowaniach.