私はパフォーマンスを向上させるために小さなCモジュールを作ったが、GHCは外部関数をインライン化せず、コストを呼び出すことで加速がなくなった。例えば 、test.h
:GHCに強制的にFFIコールをインライン化するには?
int inc (int x);
test.c
:
#include "test.h"
int inc(int x) {return x + 1;}
Test.hc
:
{-# LANGUAGE ForeignFunctionInterface #-}
module Test (inc) where
import Foreign
import Foreign.C
foreign import ccall unsafe "test.h inc" c_inc :: CInt -> CInt
inc = fromIntegral . c_inc . fromIntegral
{-# INLINE c_inC#-}
{-# INLINE inC#-}
Main.hs
:
import System.Environment
import Test
main = do {args <- getArgs; putStrLn . show . inc . read . head $ args }
メイキング:
$ gcc -O2 -c test.c
$ ghc -O3 test.o Test.hs
$ ghc --make -O3 test.o Main
$ objdump -d Main > Main.as
最後に、Main.as
に私の代わりに、望ましいinc
年代のcallq <inc>
説明書を持っています。
ghcは、生成されたコードでC関数をインライン化することを期待していますか?これは-via-Cオプションを使用するとうまくいく可能性があります。そうしないと、ghcがCコードを読み込んでコードを生成する必要があります。 – augustss
リンク時の最適化がない場合は不可能です。試してみると、HaskellとCの両方をLLVMのビットコードにコンパイルし、.bcファイルを 'llvm-link'と組み合わせ、' opt'で最適化し、 'llc'で実行可能コードを出力します。 –
@MikhailGlushenkov、コマンドシーケンスのスケッチを書くことができますか?私はhaskellコードから '.bc'ファイルを取得する方法をgoogleで調べることに失敗しました。 – leventov