当前位置: 首页 > 知识库问答 >
问题:

有约束的专门化

凌志学
2023-03-14
{-# 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秒),当使用forAlld专门化用-O3编译时。

其核心是:对于VtTest测试,加法代码被专用于ints等上的unboxed向量,而对于fctest则使用通用向量代码。在第10行,您可以看到GHC编写了plusFastCyc的专用版本,而不是第167行的通用版本。专门化的规则在第225行。我相信这条规则应该会在270号线上开火。(main6调用迭代main8y,因此main8plusFastCyc应该专门化的地方。)

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

  1. fctest中从ghc.exts中显式调用内联
  2. 删除plusFastCyc上的因子m int约束。

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

我尝试了使用(或不使用)inlineinlinablespecialize的各种选项,但似乎都不起作用。(编辑:我可能剥离了太多的plusfastcyc以使示例变小,因此inline可能会导致函数内联。这在我的实际代码中没有发生,因为plusfastcyc太大。)在这个特定的示例中,我没有得到任何match_co:needs more casesrule:LHS too complexed to desugar警告,尽管在最小化示例之前我得到了许多match_co警告。据推测,“问题”是规则中的因子m int约束;如果更改该约束,fctest的运行速度与vttest一样快。

更新

这个问题在GHC 7.8.2中仍然存在,所以这个问题仍然是相关的。

共有1个答案

江航
2023-03-14

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

这需要在语言中添加overlappinginstancesflexibleinstances

 类似资料:
  • 约束类型名J与类型名U相同的好方法是什么?

  • 我有一个通用算法,需要访问其模板类型的特征。有一个特征类可以专门用于提供这些特征。 在我的类中使用此算法时,我想将其与类中定义的私有类型一起使用。 然而,专门化只能发生在或全局范围内,而我的类是不可访问的。 是否有可能以某种方式专门化具有私有类型的模板,至少在可访问此类型的范围内? 也许可以将这个专门化声明为一个类?

  • 问题内容: 在MySQL中创建非NULL约束以使fieldA和fieldB不能都为NULL的最佳方法是什么。我不在乎任何一个本身是否为NULL,只要另一个字段具有非NULL值即可。而且,如果它们都具有非NULL值,那就更好了。 问题答案: MySQL 5.5引入了SIGNAL,因此我们不再需要Bill Karwin的答案中的额外列。Bill指出您还需要一个更新触发器,因此我也将其包括在内。

  • 我试图找出一个有四个约束的背包的逻辑。我想做一个程序,你输入你想在一餐中摄入的卡路里、脂肪、碳水化合物和蛋白质,它会在一个可能的食物列表中查找符合输入标准的最接近的食物组合。 示例 我有这些东西 4盎司牛肉(231卡路里,15克脂肪,0克碳水化合物,22克蛋白质) 1/2杯燕麦粥(260卡路里,2克脂肪,58克碳水化合物,10克蛋白质) 1/2杯黑豆(120卡路里,.5克脂肪,23克碳水化合物,7

  • 我在项目中使用bean验证,我想为现有的约束注释编写一个自定义验证器。 例如,我有一个类,它表示一个名为CustomDateTime的日期/时间。在使用此类作为例如出生日期的类中,我想用过去的日期对字段进行注释: 然后,我通过实现ConstraintValidator创建一个自定义验证器 我知道您通常会创建这样的单独注释: 但对我来说,这似乎是双重代码;-) 如何注册要与一起使用的自定义验证器?

  • 我的视图控制器中有几个视图,当检测到向上滑动时向上移动,然后当检测到向下滑动时向下移动。我使用CGRectOffset通过调整y原点来强制视图移动。我现在使用IB对视图施加了约束,我不确定移动视图的最佳方法是什么,以便它们最终在iPhone 5、6和6上的正确位置。 目前我正在做这样的事情: 用比值改变常数是否更好?因此,对于上面的约束,不使用338,这样做是否更好: