- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在让 GHC 专门化具有类约束的函数时遇到问题。我在这里有一个最小的问题示例:Foo.hs和 Main.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
,因此 main8
是 plusFastCyc
应该专门化的地方。)
我的目标是通过专门化 plusFastCyc
使 fcTest
与 vtTest
一样快。我找到了两种方法来做到这一点:
fcTest
中从 GHC.Exts
显式调用内联
。plusFastCyc
上的 Factored m Int
约束。选项1不能令人满意,因为在实际代码库中,plusFastCyc
是一个经常使用的操作,并且是一个非常大的函数,因此不应该在每次使用时都内联它。相反,GHC 应该调用 plusFastCyc
的专门版本。选项 2 并不是真正的选项,因为我需要实际代码中的约束。
我尝试了使用(和不使用)INLINE
、INLINABLE
和 SPECIALIZE
的各种选项,但似乎没有任何效果。 (编辑:我可能删除了太多的plusFastCyc
以使我的示例变小,因此INLINE
可能会导致函数被内联。这在我的真实代码中不会发生,因为 plusFastCyc
太大了。)在这个特定的示例中,我没有得到任何 match_co: needs more cases
或RULE: 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
中添加 OverlappingInstances
和 FlexibleInstances
。
有趣的是,在示例程序中,即使删除每个 SPECIALIZE
和 INLINABLE
编译指示,通过重叠实例获得的加速仍然保留。
关于haskell - 有限制的特化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21071706/
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 4 年前。
正如您在 this travis.yml 中看到的那样文件,我的代码依赖于一些第三方库,我在构建项目之前将它们安装在远程系统上。 Travis 每次推送提交时都会下载并构建这些库,这可以避免吗?我的意
我是一名优秀的程序员,十分优秀!