2013-07-01 8 views
11

Chcę zapytać, co może powodować tę różnicę. Jeśli skompiluję następujące programy i uruchomię SAME BINARIE - na niektórych platformach wynik z kodu C++ jest znacznie szybszy niż w przypadku Haskella, a druga sytuacja jest odwrotna.C++ i kody Haskella różnią się czasem wykonania na różnych maszynach

Dodatkowo istnieje duża różnica w wydajności końcowych plików binarnych w zależności od platformy, na której zostały zbudowane. (Każda platforma używa tych samych flag i tych samych wersji LVM i clang)

Kody są zoptymalizowane i powinny działać z podobną wydajnością - patrz: Can Haskell optimize function calls the same way Clang/GCC does?.

Chcę Cię zapytać, jak to jest możliwe.

kod C++:

#include <cstdio> 
#include <cstdlib> 

int b(const int x){ 
    return x+5; 
} 

int c(const int x){ 
    return b(x)+1; 
} 

int d(const int x){ 
    return b(x)-1; 
} 

int a(const int x){ 
    return c(x) + d(x); 
} 

int main(int argc, char* argv[]){ 
    printf("Starting...\n"); 
    long int iternum = atol(argv[1]); 
    long long int out = 0; 
    for(long int i=1; i<=iternum;i++){ 
     out += a(iternum-i); 
    } 
    printf("%lld\n",out); 
    printf("Done.\n"); 
} 

skompilowany z kodu clang++ -O3 main.cpp

Haskell:

module Main where 
import qualified Data.Vector as V 
import System.Environment 
b :: Int -> Int 
b x = x + 5 
c x = b x + 1 
d x = b x - 1 
a x = c x + d x 
main = do 
    putStrLn "Starting..." 
    args <- getArgs 
    let iternum = read (head args) :: Int in do 
     putStrLn $ show $ V.foldl' (+) 0 $ V.map (\i -> a (iternum-i)) 
     $ V.enumFromTo 1 iternum 
     putStrLn "Done." 

skompilowany ghc -O3 --make -fforce-recomp -fllvm ghc-test.hs

Wyniki (Testowanie tej samej binarne na różne platformy)

// binaries compiled on Ubuntu: 
Ubuntu x64 @ Intel i7-3610QM CPU @ 2.30GHz : C++:0.775s, GHC:1.01s 
Gentoo x64 @ Intel i7-Q720 CPU @ 1.6GHz : C++:3.6s, GHC:2.1s 

// binaries compiled on Gentoo: 
Ubuntu x64 @ Intel i7-3610QM CPU @ 2.30GHz : C++:0.782s, GHC:1.01s 
Gentoo x64 @ Intel i7-Q720 CPU @ 1.6GHz : C++:2.3s, GHC:1.3s 
+3

Dane wyjściowe kompilatorów można zoptymalizować dla różnych zestawów układów. Powtórzę to, co powiedziałem na twoje ostatnie pytanie: sprawdź wyniki montażu. – chrisaycock

+0

@chrisaycock Nie widziałem twojego ostatniego komentarza - zrobię to –

+14

@ H2CO3: "C++ jest językiem kompilowanym, Haskell jest interpretowany". To nieprawda. GHC jest kompilatorem. Tworzy natywny kod. Języki nie są interpretowane ani kompilowane z natury, ale można napisać interpreter lub kompilator dla dowolnego praktycznego języka, w tym C++. –

Odpowiedz

16

Gdybym skompilować następujące programy i wykonujących te same binaria - na niektórych platformach ten wynikał z kodu C++ jest znacznie szybsze niż Haskell jeden na drugi sytuacja jest odwrotna.

Dodatkowo istnieje duża różnica w wydajności końcowych plików binarnych w zależności od platformy, na której zostały zbudowane. (Każda platforma wykorzystuje te same flagi i te same wersje LVM i szczęk)

Widzisz wpływu brzydkie szczegóły operacyjne prawdziwych komputerów:

  • łącznikowych optymalizacje
  • różnych wersjach dynamicznie ładowane biblioteki
  • jakość generowania kodu zespołu dla danej mikro architektury
  • dostęp do specjalistycznych instrukcji
  • cache rozmiarach scheduler systemu
  • operacyjnego, przydzielania ...
  • opóźnienia pamięci

Istnieje ogromna ilość kodu i sprzętu, które różnią się między tymi dwoma platformami, co oznacza, że ​​możesz skończyć pomiaru różnych rzeczy .

Nie ma powodu oczekiwać, że wydajność będzie taka sama lub nawet w tym samym stosunku. W przypadku mikro-benchmarków nie jest niczym niezwykłym odwracanie względnych porządków podczas przenoszenia platform.

Powiązane problemy