2013-07-01 10 views
11

この違いを引き起こす可能性があることについてお聞きしたいと思います。以下のプログラムをコンパイルして同じバイナリを実行すると、一部のプラットフォームではC++コードの結果がハスケルのコードよりもはるかに高速ですが、他の状況は逆です。C++とHaskellのコードは、異なるマシンで実行時間が異なります

追加ビルドされたプラットフォームに応じて、最終的なバイナリのパフォーマンスに大きな違いがあります。 (各プラットフォームは同じフラグと同じバージョンのLVMとclangを使用します)

コードは最適化されており、同等のパフォーマンスで動作する必要があります。Can Haskell optimize function calls the same way Clang/GCC does?を参照してください。

どうすれば可能ですか?

C++コード:ghc -O3 --make -fforce-recomp -fllvm ghc-test.hs

結果(SAMEバイナリ上試験でコンパイル

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." 

clang++ -O3 main.cpp

Haskellコードでコンパイル

#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"); 
} 

私は、次のプログラムをコンパイルし、同じバイナリを実行する場合、異なるプラットフォーム)

// 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

コンパイラの出力は、さまざまなチップセットに対して最適化できます。私はあなたの最後の質問について言ったことを繰り返します:アセンブリの出力を確認してください。 – chrisaycock

+0

@chrisaycock前回はあなたのコメントが見えませんでした - 私はそれを実行します –

+14

@ H2CO3: "C++はコンパイルされた言語です、ハスケルは解釈済みです"これは誤りです。 GHCはコンパイラです。ネイティブコードを生成します。言語は本質的に解釈もコンパイルもされませんが、C++を含む実用的な言語用のインタープリタやコンパイラを書くことができます。 –

答えて

16

は - いくつかのプラットフォーム上で一つはC++コードに起因Haskellの1が、他に状況は反対であるよりもはるかに高速です。

追加ビルドされたプラットフォームに応じて、最終的なバイナリのパフォーマンスに大きな違いがあります。

  • リンカの最適化の
  • 異なるバージョン:

(各プラットフォームは同じフラグとLVMと打ち鳴らすの同じバージョンを使用しています)あなたは、実際のコンピュータの厄介な動作の詳細の影響を見ています動的にロードされるライブラリ

  • 特定のマイクロアーキテクチャのアセンブリコードの品質
  • 専用命令へのアクセス
  • キャッシュを使用すると、異なるものを測定してしまうことを意味し、
  • オペレーティングシステムのスケジューラ、アロケータ、...
  • メモリレイテンシ
  • 2つのプラットフォーム間で異なるコードとハードウェアの膨大な量がありますがサイズ。

    パフォーマンスが同じか、同じ比率であると予測する理由はありません。マイクロベンチマークの場合、プラットフォームを動かすときに相対的な順序を反転することは珍しいことではありません。

    関連する問題