Haskell コンパイラと C++ コンパイラが同じ方法で関数呼び出しを最適化できるかどうかお尋ねしたいと思います。次のコードを見てください。次の例では、Haskell は C++ よりも大幅に高速です。
Haskell は LLVM にコンパイルでき、LLVM パスによって最適化できると聞いたことがあります。さらに、Haskell には内部でいくつかの大幅な最適化が行われていると聞いています。ただし、次の例は同じパフォーマンスで機能するはずです。私は尋ねたい:
- C++ のサンプル ベンチマークが Haskell のベンチマークよりも遅いのはなぜですか?
- コードをさらに最適化することは可能ですか?
(LLVM-3.2 と GHC-7.6 を使用しています)。
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");
}
でコンパイルclang++ -O3 main.cpp
ハスケルコード:
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."
でコンパイルghc -O3 --make -fforce-recomp -fllvm ghc-test.hs
速度の結果:
Running testcase for program 'cpp/a.out'
-------------------
cpp/a.out 100000000 0.0% avg time: 105.05 ms
cpp/a.out 200000000 11.11% avg time: 207.49 ms
cpp/a.out 300000000 22.22% avg time: 309.22 ms
cpp/a.out 400000000 33.33% avg time: 411.7 ms
cpp/a.out 500000000 44.44% avg time: 514.07 ms
cpp/a.out 600000000 55.56% avg time: 616.7 ms
cpp/a.out 700000000 66.67% avg time: 718.69 ms
cpp/a.out 800000000 77.78% avg time: 821.32 ms
cpp/a.out 900000000 88.89% avg time: 923.18 ms
cpp/a.out 1000000000 100.0% avg time: 1025.43 ms
Running testcase for program 'hs/main'
-------------------
hs/main 100000000 0.0% avg time: 70.97 ms (diff: 34.08)
hs/main 200000000 11.11% avg time: 138.95 ms (diff: 68.54)
hs/main 300000000 22.22% avg time: 206.3 ms (diff: 102.92)
hs/main 400000000 33.33% avg time: 274.31 ms (diff: 137.39)
hs/main 500000000 44.44% avg time: 342.34 ms (diff: 171.73)
hs/main 600000000 55.56% avg time: 410.65 ms (diff: 206.05)
hs/main 700000000 66.67% avg time: 478.25 ms (diff: 240.44)
hs/main 800000000 77.78% avg time: 546.39 ms (diff: 274.93)
hs/main 900000000 88.89% avg time: 614.12 ms (diff: 309.06)
hs/main 1000000000 100.0% avg time: 682.32 ms (diff: 343.11)
EDIT もちろん、言語の速度を比較することはできませんが、実装の速度を比較します。
しかし、Ghc と C++ のコンパイラが関数呼び出しを同じように最適化できるかどうか、私は興味があります
あなたの助けに基づいて、新しいベンチマークとコードで質問を編集しました:)