- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
如果我想调用多个 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/
我有一个问题,多次执行 ActorSystem system = ActorSystem.create("System"); 是否会提高生产力,或者我必须执行一次并使用一个引用? 最佳答案 您应该仅创
我希望学生能够在收到付款请求之前访问 Moodle 中的前几节课。我在 Google 上搜索了好久,但一无所获,还搜索了我在这里能想到的所有可能的术语,但还是没有找到。因此,对于缺乏贡献的研究/证据,
有什么方法可以用 PHP 分摊 paypal 费用吗?我希望 90% 转到一个帐户,10% 转到另一个帐户,但是当向此人收费时,它看起来应该只是转到 10% 的帐户。我希望使用 IPN 向此人收费。无
在使用 Adaptive Payment API 完成链式或并行支付的情况下,我有一个关于 Paypal 如何计算适用于每个接收方的费用的答案。 费用是按发件人支付的总金额计算的吗?在这种情况下,每个
SINCH 是否会对双方(调用者和接收者)的通信收费? 正如我所见,如果我使用 SINCH 执行应用到应用的通话,那么我的通话时间将从通话双方的通话时间中扣除。 我知道 sinch 允许 2500 分
已关闭。这个问题是 off-topic 。目前不接受答案。 想要改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 已关闭13 年前。 Improve th
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 这个问题似乎不是关于 a specific programming problem, a software
我一直在尝试将 hr_expenses 表单中的某些字段复制到我的自定义模块purchase_orders 中。 下面的方法是为我在扩展的 hr_expenses.py 文件中执行此操作而编写的: d
Paypal 费用是否适用于其 API 内的任何调用或特定调用? 例如,如果我在/billing-agreements api 中使用任何调用,我是否会被收取 2.9% 或更少的费用,外加每笔交易 0
在 Woocommerce 中,我们试图在通过 Paypal 支付网关购买商品时向订单添加额外费用。 我们通过这种方式更改了发送到 Paypal 的价格: add_filter('woocommerc
我正在尝试设置 Stripe Connect 并且需要 首先通过创建客户向买家收费, 然后生成一个token,最后 使用此 token 向客户收费。 只要买家和卖家不是 Stripe Connect
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 去年关闭。 Improve this
使用 .NET 库如何确定查询的 RU 费用。它返回 IQueryable,我不知道如何记录它。如何记录所有请求的 RU 的奖励积分。 简单的代码但不返回 RU: var docs = Docume
我有一个有一些购买选项的应用程序。但是,我不想通过应用程序本身来实现它。为此,我已经有一个购买网站。 那么我可以创建一个从我的应用程序到相应网页的重定向页面吗? 我的应用程序会被拒绝吗? 或者有更好的
我正在尝试弄清楚如何(粗略地)计算我正在考虑创建的某些工作角色的预期成本。 TLDR; 如果您的工作人员Sleep(someTime)/Sleeping,azure 是否会向您收取 $$ 费用? 详细
我是 Lambda 的新手,正在尝试了解如何在 Lambda 函数中处理 Stripe charge。 我的应用程序从 Stripe API 创建 token ,现在我需要将该 token 发送到 L
我为管理用户使用easyui表,我正确添加了所有脚本,但是与jquery.easyui.min.js发生冲突我尝试消除所有js以查看是否有效,但是,它不起作用,所以不是js冲突。 有人遇到过类似的问题
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 7 年前。 Improve this ques
有谁知道是否有公开可用的 PayPal 资源可以让我在我的 Magento 代码中计算交易费用? 例如,如果有人以 1.00 美元的价格购买东西,我想知道其中的 0.15 美元是否是 PayPal 费
我只是想知道是否有办法检索 strip 中多个 charges_id 的费用。 例如在 docs展示如何获得一次充电。但是我们需要多次收费。所以,我们不想多次调用 stripe 方法 retrieve
我是一名优秀的程序员,十分优秀!