gpt4 book ai didi

c - Haskell FFI 进入 C 并返回需要多少费用?

转载 作者:太空狗 更新时间:2023-10-29 16:23:11 25 4
gpt4 key购买 nike

如果我想调用多个 C 函数,每个函数都取决于前一个函数的结果,创建一个包装器 C 函数来处理这三个调用是否更好?它的成本是否与不转换类型而使用 Haskell FFI 的成本相同?

假设我有以下 Haskell 代码:

foo :: CInt -> IO CInt
foo x = do
a <- cfA x
b <- cfB a
c <- cfC c
return c

每个函数 cf* 都是一个 C 调用。

就性能而言,创建单个 C 函数(如 cfABC)并在 Haskell 中仅进行一次外部调用是否更好?

int cfABC(int x) {
int a, b, c;
a = cfA(x);
b = cfB(a);
c = cfC(b);
return c;
}

haskell 代码:

foo :: CInt -> IO CInt
foo x = do
c <- cfABC x
return c

如何衡量来自 Haskell 的 C 调用的性能成本?不是 C 函数本身的成本,而是从 Haskell 到 C 并返回的“上下文切换”的成本。

最佳答案

答案主要取决于外部调用是安全还是不安全调用。

一个 unsafe C 调用基本上只是一个函数调用,所以如果没有(非平凡的)类型转换,如果你进行三个外部调用,就会有三个函数调用,而当你进行在 C 中编写一个包装器,这取决于在编译 C 时可以内联多少组件函数,因为 GHC 无法内联对 C 的外部调用。这样的函数调用通常非常便宜(它只是参数的副本和代码的跳转),所以两者之间的差异很小,当没有 C 函数可以内联到包装器中时,包装器应该稍微慢一些,并且当所有内容都可以内联时稍微快一些[在我的基准测试中确实如此,+1.5ns resp。 -3.5ns,其中三个外部调用花费了大约 12.7ns 来返回参数]。如果函数做了一些重要的事情,那么差异可以忽略不计(如果它们没有做任何重要的事情,你最好用 Haskell 编写它们,让 GHC 内联代码)。

安全 C 调用涉及保存一些重要的状态、锁定、可能产生新的操作系统线程,因此需要更长的时间。然后,与外部调用的成本相比,在 C 中调用一个函数的小开销可以忽略不计 [除非传递参数需要不寻常的复制量,许多巨大的 struct 左右]。在我什么都不做的基准测试中

{-# LANGUAGE ForeignFunctionInterface #-}
module Main (main) where

import Criterion.Main
import Foreign.C.Types
import Control.Monad

foreign import ccall safe "funcs.h cfA" c_cfA :: CInt -> IO CInt
foreign import ccall safe "funcs.h cfB" c_cfB :: CInt -> IO CInt
foreign import ccall safe "funcs.h cfC" c_cfC :: CInt -> IO CInt
foreign import ccall safe "funcs.h cfABC" c_cfABC :: CInt -> IO CInt

wrap :: (CInt -> IO CInt) -> Int -> IO Int
wrap foo arg = fmap fromIntegral $ foo (fromIntegral arg)

cfabc = wrap c_cfABC

foo :: Int -> IO Int
foo = wrap (c_cfA >=> c_cfB >=> c_cfC)

main :: IO ()
main = defaultMain
[ bench "three calls" $ foo 16
, bench "single call" $ cfabc 16
]

所有 C 函数只返回参数,单个包装调用的平均值略高于 100ns [105-112],而三个单独调用的平均值约为 300ns [290-315]。

因此,安全 c 调用大约需要 100ns,通常,将它们打包成单个调用会更快。但是,如果被调用的函数做了一些足够重要的事情,那么差异就无关紧要了。

关于c - Haskell FFI 进入 C 并返回需要多少费用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14519905/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com