Koszty porównań i przesunięć

0

Witam. Może ktoś mi przybliżyć różnice w kosztach wykonywania operacji porównania wartości a przesuwania referencji do wartości?? Chodzi o koszty obliczeń. Dzięki z góry.

0

@Sopelek Sam przecież możesz zawsze puścić testy i sprawdzić czas w nanosekundach.

0

To zależy od bardzo wielu czynników. Wyniki na twoim komputerze mogą się drastycznie różnić od wyników na innym komputerze. Do tego dochodzą jeszcze optymalizacje w JVMie, niektóre z nich są dość drastyczne :] Jeśli np spojrzysz na kod: Dlaczego foreach jest gorsze od for (beta) to możesz dojść do wniosku, że tworzenie obiektów w Javie i wywoływanie metod jest za darmo, ale w rzeczywistości tak nie jest. Po prostu w tym przypadku JVM sobie ładnie zoptymalizował kod. Mogę dodać jeszcze, że nawet nie da się policzyć czasu wykonywania pojedynczej instrukcji procesora, gdyż obecne procesory są wielopotokowe i mają wykonywanie instrukcji poza kolejnością. Dlatego czasem procesor jest w stanie wykonać kilka instrukcji naraz, a czasem wykonuje jedną przez wiele taktów. Drobne zmiany w kodzie mogą zauważalnie zmienić wydajność, gdyż heurystyki optymalizujące kod mogą się nie odpalić.

Bardziej wysokopoziomowe porównania są np tutaj: http://shootout.alioth.debian.org/u64q/java.php z tym, że moim zdaniem niektóre porównania są trochę nie na miejscu, np binary_trees, gdzie Java używa normalnej alokacji obiektów, a G++ używa pul obiektów (bez pul jest 4x wolniejszy). W pidigits znowu testowana jest głównie szybkość wywoływania funkcji z biblioteki GMP, która jest napisana w C/ C++, a więc C/ C++ naturalnie ma minimalny narzut na wywołania metod w tym teście.

1

@Sopelek
Są listy operacji procesorów podające czasy wykonania wg miary ilości cykli procesora. Generalnie operacje złożone trwają dłużej od operacji prostych, czyli pierwiastkowanie > potęgowanie > dzielenie > mnożenie> dodawanie/odejmowanie > operacje bitowe. Kiedyś na procesorach, które zrealizowane sprzętowo miały tylko 2-4 ostatnie operacje te różnice były znaczące. Na współczesnych procesorach udaje się zredukować te różnice między np. dodawaniem, mnożeniem i dzieleniem - czasem nawet do zera. Ale koszt złożoności może i tak gdzieś wyjść. Na przykład złożona operacja rozłożona na wiele modułów arytmetycznych CPU wykona się tak samo szybko jak dodawanie, ale operacja prosta wykorzysta tylko jeden moduł, zamiast wielu. W takim wypadku kod wielowątkowy będzie w stanie wykonać kilka dodawań w tym samym cyklu (i o ile budowa procesora na to pozwoli), ale już potęgowania mogą zostać ustawione w kolejkę do wykonania i może się okazać, że łączne wykonanie wszystkich wątków będzie wolniejsze.
W przypadku Javy gdzie operacje są tłumaczone dwustopniowo - najpierw do bajtkodu, a potem (ewentualnie) do maszynowego - zależności te są jeszcze luźniejsze.

1

Jeszcze zapomniałem dopisać o takich operacjach jak przesyły danych. Przesunięcia w ramach operacji, które najczęściej dokonują się w rejestrach trwają podobnie jak operacje bitowe, czyli zwykle nie wolniej niż 1 cykl zegarowy. Natomiast pamięci RAM mogą być bardzo wolne - np. dostęp do pamięci DDR3 zajmuje w najlepszym wypadku 6-7 taktów, a w najgorszym aż 24-28. To bardzo wolno i gdyby nie szybka pamięć cache, która z dostępem 1-2 takty obejmuje >95% trafień, to pamięć DRAM byłaby wąskim gardłem każdego komputera. Dlatego wszelkie dostępy do pamięci w niedużych ilościach i często używane (np. pola i metody obiektów) są szybkie. Ale jeżeli są to dostępy masowe obejmujące wiele MB, to cache przestanie je obejmować i takie operacje mogą się stać wyraźnie wolniejsze niż początkowo. Jednym z przykładów takich operacji jest sortowanie wielkich tablic - pojedynczy odczyt lub zapis 4-8 bajtów staje się znacząco wolniejszy (szczególnie na adresach nie będących wielokrotnościami 4/8). Również odczyty i zapisy na nośniki masowe powoduje przerzucanie wielkich ilości danych między buforami, co przekłada się na powolny transfer każdego słowa maszynowego, ale tutaj spowalniaczem o rzędy wielkości większym jest sam zapis lub odczyt nośnika (w porównaniu do DRAM - dość wolny na SSD, wolniejszy na pendrive'y/karty flash i super wolny na HDD).

0

Jak ktoś chce poręczny poradnik nt niskopoziomowych optymalizacji pod x86 to http://agner.org/optimize/ jest raczej dobrym wyborem.

Czasy wykonań instrukcji są np tutaj: http://instlatx64.atw.hu/
Dla przykładu opóźnienia w dostępie do pamięci w Intel i7 2600: http://users.atw.hu/instlatx64/GenuineIntel00206A7_SandyBridge3_MemLatX64.txt
Dostęp/ opóźnienie:

  • cache L1: 4 takty,
  • cache L2: 11 taktów,
  • cache L3: 18 taktów,
  • RAM: 184 takty,

1 użytkowników online, w tym zalogowanych: 0, gości: 1