GHC Haskell中专门的导入函数

我现在正在处理一个项目,我正在处理Prim typeclass,并且需要确保我编写的特定函数是专用的。 也就是说,我需要确保当我调用它时,我会得到一个专用版本的函数,其中Prim字典被内联到特定的定义中,而不是在运行时传递。

幸运的是,这在GHC中是一个很好理解的东西。 你可以写:

{-# SPECIALIZE foo :: ByteArray Int -> Int #-}
foo :: Prim a => ByteArray a -> Int
foo = ...

而在我的代码中,这种方法工作正常。 但是,由于类型类是开放的,因此可能存在Prim实例,但是在编写库Prim不知道。 这给我带来了这个问题。 GHC用户指南的SPECIALIZE文档提供了两种使用方法。 首先是将SPECIALIZE放在定义的位置,就像我在上面的例子中所做的那样。 第二种方法是将SPECIALIZE注置于另一个导入函数的模块中。 作为参考,用户手册提供的示例是:

module Map( lookup, blah blah ) where
  lookup :: Ord key => [(key,a)] -> key -> Maybe a
  lookup = ...
  {-# INLINABLE lookup #-}

module Client where
  import Map( lookup )

  data T = T1 | T2 deriving( Eq, Ord )
  {-# SPECIALISE lookup :: [(T,a)] -> T -> Maybe a

我遇到的问题是这在我的代码中不起作用。 该项目在github上,相关的行是:

  • bench/Main.hs线24
  • src/BTree/Compact.hs第149行
  • 要运行基准测试,请运行以下命令:

    git submodule init && git submodule update
    cabal new-build bench && ./dist-newstyle/build/btree-0.1.0.0/build/bench/bench
    

    当我运行基准时,有一部分输出结果为:

    Off-heap tree, Amount of time taken to build:
    0.293197796
    

    如果我取消对BTree.Compact的第151行的评论,那么基准的那部分运行速度会快50倍:

    Off-heap tree, Amount of time taken to build:
    5.626834e-2
    

    值得指出的是,有问题的函数modifyWithM是巨大的。 它的实现超过100行,但我认为这不应该有所作为。 该文件声称:

    ...将f的定义标记为INLINABLE,以便GHC保证揭示展开,而不管它有多大。

    所以,我的理解是,如果专注于定义网站的工作,应该始终可以专注于呼叫站点。 我很感谢来自那些比我更了解这种机器的人的任何见解,如果事情不清楚,我很乐意提供更多信息。 谢谢。

    编辑:我已经意识到,在这篇文章中我链接到的git commit中,基准代码存在问题。 它重复插入相同的值。 但是,即使在解决这个问题之后,专业化问题仍然在发生。

    链接地址: http://www.djcxy.com/p/33201.html

    上一篇: Specializing Imported Function in GHC Haskell

    下一篇: Guarantee of Specialization with GHC