如何强制GHC内联FFI调用?

时间:2013-01-07 15:55:28

标签: haskell ghc ffi

我制作了小型C模块以提高性能,但GHC并没有内联外部功能,而且调用成本消除了加速。 例如,test.h

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 callq <inc>我有inc条指令,而不是理想的{{1}}。

1 个答案:

答案 0 :(得分:9)

GHC不会通过其asm后端或LLVM后端内联C代码。通常情况下,如果你打电话的东西真的花了很多钱,你只会因为性能原因打电话给C。增加一个int并不是一件事,因为我们已经有了这个原则。

现在,如果你通过C调用,你可能会让GCC内联(检查生成的程序集)。

但是,现在您可以做一些事情来降低通话费用:

foreign import ccall unsafe "test.h inc" c_inc :: CInt -> CInt

inc = fromIntegral . c_inc . fromIntegral

inc提供类型签名。你在这里支付宝贵的周期转换为整数。

将调用标记为“不安全”,这样就可以在调用之前将运行时添加为书签。

测量FFI呼叫开销 - 它应该在纳秒内。但是,如果您发现它仍然过于昂贵,可以write a new primop and jump to it directly.但最好先提供criterion个数字。