gpt4 book ai didi

haskell - 有限制的特化

转载 作者:行者123 更新时间:2023-12-02 08:02:56 24 4
gpt4 key购买 nike

我在让 GHC 专门化具有类约束的函数时遇到问题。我在这里有一个最小的问题示例:Foo.hsMain.hs 。这两个文件编译(GHC 7.6.2,ghc -O3 Main)并运行。

注意:Foo.hs 确实被精简了。如果你想了解为什么需要约束,可以看多一点代码 here 。如果我将代码放在单个文件中或进行许多其他细微更改,GHC 只会内联对 plusFastCyc 的调用。这在实际代码中不会发生,因为 plusFastCyc 太大,GHC 无法内联,即使标记为 INLINE 也是如此。重点是专门plusFastCyc的调用,而不是内联它。 plusFastCyc 在实际代码中的很多地方都会被调用,因此即使我可以强制 GHC 这样做,复制这么大的函数也是不可取的。

感兴趣的代码是 Foo.hs 中的 plusFastCyc,复制如下:

{-# INLINEABLE plusFastCyc #-}
{-# SPECIALIZE plusFastCyc ::
forall m . (Factored m Int) =>
(FastCyc (VT U.Vector m) Int) ->
(FastCyc (VT U.Vector m) Int) ->
(FastCyc (VT U.Vector m) Int) #-}

-- Although the next specialization makes `fcTest` fast,
-- it isn't useful to me in my real program because the phantom type M is reified
-- {-# SPECIALIZE plusFastCyc ::
-- FastCyc (VT U.Vector M) Int ->
-- FastCyc (VT U.Vector M) Int ->
-- FastCyc (VT U.Vector M) Int #-}

plusFastCyc :: (Num (t r)) => (FastCyc t r) -> (FastCyc t r) -> (FastCyc t r)
plusFastCyc (PowBasis v1) (PowBasis v2) = PowBasis $ v1 + v2

Main.hs 文件有两个驱动程序:vtTest(运行时间约为 3 秒)和 fcTest(运行时间约为 83 秒)使用 -O3 使用 forall'd 专门化进行编译时的秒数。

core shows对于 vtTest 测试,附加代码专门用于 Int 上的 Unboxed 向量,等等,而通用向量代码用于 fcTest。在第 10 行,您可以看到 GHC 确实编写了 plusFastCyc 的专用版本,与第 167 行的通用版本相比。专门化的规则位于第 225 行。我相信该规则应该在第 270 行触发。(main6 调用 iterate main8 y,因此 main8plusFastCyc 应该专门化的地方。)

我的目标是通过专门化 plusFastCyc 使 fcTestvtTest 一样快。我找到了两种方法来做到这一点:

  1. fcTest 中从 GHC.Exts 显式调用内联
  2. 删除 plusFastCyc 上的 Factored m Int 约束。

选项1不能令人满意,因为在实际代码库中,plusFastCyc是一个经常使用的操作,并且是一个非常大的函数,因此不应该在每次使用时都内联它。相反,GHC 应该调用 plusFastCyc 的专门版本。选项 2 并不是真正的选项,因为我需要实际代码中的约束。

我尝试了使用(和不使用)INLINEINLINABLESPECIALIZE 的各种选项,但似乎没有任何效果。 (编辑:我可能删除了太多的plusFastCyc以使我的示例变小,因此INLINE可能会导致函数被内联。这在我的真实代码中不会发生,因为 plusFastCyc 太大了。)在这个特定的示例中,我没有得到任何 match_co: needs more casesRULE: LHS too complicated to desugar (和 here )警告,尽管在最小化示例之前我收到了许多 match_co 警告。据推测,“问题”是规则中的 Factored m Int 约束;如果我更改该约束,fcTest 的运行速度将与 vtTest 一样快。

我是否在做 GHC 不喜欢的事情?为什么 GHC 不专门化 plusFastCyc,我该如何制作它?

更新

该问题在 GHC 7.8.2 中仍然存在,因此这个问题仍然相关。

最佳答案

GHC 还提供了一个选项来SPECIALIZE 类型类实例声明。我用 Foo.hs 的(扩展)代码尝试了这一点,输入以下内容:

instance (Num r, V.Vector v r, Factored m r) => Num (VT v m r) where 
{-# SPECIALIZE instance ( Factored m Int => Num (VT U.Vector m Int)) #-}
VT x + VT y = VT $ V.zipWith (+) x y

但是,这一更改并未达到预期的加速效果。实现性能改进的方法是手动添加具有相同函数定义的VT U.Vector m Int类型的专用实例,如下所示:

instance (Factored m Int) => Num (VT U.Vector m Int) where 
VT x + VT y = VT $ V.zipWith (+) x y

这需要在 LANGUAGE 中添加 OverlappingInstancesFlexibleInstances

有趣的是,在示例程序中,即使删除每个 SPECIALIZEINLINABLE 编译指示,通过重叠实例获得的加速仍然保留。

关于haskell - 有限制的特化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21071706/

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