GHC 中自动专业化的传递性

2023-12-29

From the docs http://www.haskell.org/ghc/docs/7.6.3/html/users_guide/pragmas.html#idp49866112对于 GHC 7.6:

[你]通常甚至一开始就不需要 SPECIALIZE pragma。编译模块 M 时,GHC 的优化器(使用 -O)自动考虑 M 中声明的每个顶级重载函数,并将其专门用于 M 中调用它的不同类型。优化器还考虑每个导入的 INLINABLE 重载函数,并将其专门用于 M 中称为的不同类型。

and

此外,给定函数 f 的 SPECIALIZE pragma,GHC 将自动为 f 调用的任何类型类重载函数创建特化,如果它们与 SPECIALIZE pragma 位于同一模块中,或者它们是 INLINABLE;等等,传递性地。

所以 GHC 应该自动专业化一些/大多数/全部(?) https://stackoverflow.com/questions/21071706/specialization-with-constraints功能标记INLINABLE without一个编译指示,如果我使用显式编译指示,则专业化是传递的。我的问题是: 是个auto- 专业化传递?

具体来说,这是一个小例子:

Main.hs:

import Data.Vector.Unboxed as U
import Foo

main =
    let y = Bar $ Qux $ U.replicate 11221184 0 :: Foo (Qux Int)
        (Bar (Qux ans)) = iterate (plus y) y !! 100
    in putStr $ show $ foldl1' (*) ans

Foo.hs:

module Foo (Qux(..), Foo(..), plus) where

import Data.Vector.Unboxed as U

newtype Qux r = Qux (Vector r)
-- GHC inlines `plus` if I remove the bangs or the Baz constructor
data Foo t = Bar !t
           | Baz !t

instance (Num r, Unbox r) => Num (Qux r) where
    {-# INLINABLE (+) #-}
    (Qux x) + (Qux y) = Qux $ U.zipWith (+) x y

{-# INLINABLE plus #-}
plus :: (Num t) => (Foo t) -> (Foo t) -> (Foo t)
plus (Bar v1) (Bar v2) = Bar $ v1 + v2

GHC 专门呼吁plus,但是确实not专门化(+) in the Qux Num会降低性能的实例。

然而,一个明确的杂注

{-# SPECIALIZE plus :: Foo (Qux Int) -> Foo (Qux Int) -> Foo (Qux Int) #-}

结果是及物的正如文档所示,专业化,所以(+)是专门化的,代码速度快了 30 倍(均使用-O2)。这是预期的行为吗?我应该只期待(+)通过明确的编译指示来传递地专门化?


UPDATE

7.8.2 的文档没有改变,并且行为是相同的,所以这个问题仍然相关。


简短的答案:

据我了解,这个问题的要点如下:

  • “自动专业化是否具有传递性?”
  • 我是否应该只期望 (+) 通过显式编译指示传递地专门化?
  • (显然是故意的)这是 GHC 的错误吗?与文档不一致吗?

AFAIK,答案是否定的,大部分是肯定的,但还有其他方法,也不是。

代码内联和类型应用程序专门化是速度(执行时间)和代码大小之间的权衡。默认级别可以在不使代码膨胀的情况下获得一些加速。选择更详尽的级别由程序员自行决定SPECIALISE pragma.

解释:

优化器还考虑每个导入的 INLINABLE 重载函数,并将其专门用于 M 中调用它的不同类型。

Suppose f是一个函数,其类型包含类型变量a受类型类约束C a。 GHC 默认专门化f对于类型应用程序(替换a for t) if f在 (a) 同一模块中的任何函数的源代码中使用该类型应用程序进行调用,或者 (b) 如果f被标记INLINABLE,然后是任何其他模块imports f from B。因此,自动特化不是传递性的,它只涉及INLINABLE导入和调用的函数在源代码中 of A.

在您的示例中,如果您重写实例Num如下:

instance (Num r, Unbox r) => Num (Qux r) where
    (+) = quxAdd

quxAdd (Qux x) (Qux y) = Qux $ U.zipWith (+) x y
  • quxAdd不是专门进口的Main. Main导入实例字典Num (Qux Int),这本词典包含quxAdd在记录中(+)。然而,虽然导入了词典,但词典中使用的内容却没有导入。
  • plus不打电话quxAdd,它使用存储的函数(+)记录在实例字典中Num t。该字典在调用站点设置(在Main)由编译器执行。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

GHC 中自动专业化的传递性 的相关文章

  • QuickCheck是否可以生成任意函数

    我试图为身份编写一个 QuickCheck 测试 f y f y 我最初的计划是编写一个返回函数和整数的任意生成器 具有签名Gen Int gt Int Int 并在prop DollerDoesNothing使用 不使用测试该功能应用程序
  • 找不到模块“Yesod”

    我有以下代码 LANGUAGE TypeFamilies QuasiQuotes MultiParamTypeClasses TemplateHaskell OverloadedStrings module Simple where imp
  • 在 monad 转换器类型类中使用列表 monad?

    我的目标是创建一个在 ReaderT WriterT 堆栈或 RWS 堆栈中使用列表 monad 的函数 更一般地说 如何在 mtl 类型类 例如 MonadReader MonadWriter 中使用列表 monad 我为什么要尝试这样做
  • 在 Haskell 中合并两个列表

    无法弄清楚如何合并两个列表通过以下方式在哈斯克尔 INPUT 1 2 3 4 5 11 12 13 14 OUTPUT 1 11 2 12 3 13 4 14 5 我想提出一个更懒的合并版本 merge ys ys merge x xs y
  • 如何在不声明新数据的情况下更改类型(String,Int)元组的 Ord 实例?

    我正在尝试对类型列表进行排序 String Int 默认情况下 它按字符串排序 然后按整数排序 如果字符串相等 我希望它是相反的 首先比较整数 然后如果相等则比较字符串 另外 我不想切换到 Int String 我找到了一种通过定义实例来实
  • ST monad 是如何工作的?

    我知道 ST monad 有点像 IO 的弟弟 而 IO 又是添加了状态 monadRealWorld魔法 我可以想象状态 也可以想象 RealWorld 以某种方式放入 IO 中 但每次我写一个类型签名ST the sST monad 的
  • 类型级别集结合律的证明

    我试图证明类型级函数Union https hackage haskell org package type level sets 0 8 5 0 docs Data Type Set html t Union是关联的 但我不确定应该如何完
  • 如何更换HXT中的节点?

    给定一个示例 xml 文件
  • 纯 Haskell 代码需要线程池吗?

    In 现实世界 Haskell 第 28 章 软件事务内存 http book realworldhaskell org read software transactional memory html 开发了一个并发网络链接检查器 它获取网
  • 在 Haskell 中获取玫瑰树的根

    最近我开始学习 Haskell 并在以下练习中遇到困难 Write functions root Rose a gt a and children Rose a gt Rose a that return the value stored
  • Haskell 项目可以使用 cmake 吗?

    我正在计划一个用 Haskell 编写的项目 也许也有一些部分是用 C 编写的 对于构建系统 我决定不选择 Haskell 程序 cabal 的常见选择 主要是因为我想了解其他语言的构建程序是如何工作的 我听说过 CMake 我认为这是一个
  • 使用带有两个列表而不是一个列表的地图。可以筑巢吗?

    我需要多次运行一个带有两个参数的函数 我有两个包含这些参数的列表 我希望能够使用map或类似的东西用相应的参数调用函数 我要调用的函数具有以下类型 runParseTest String gt String gt IO 列表的创建方式如下
  • 树莓派 2 上的 GHCi?

    我正在开发一些在 raspberry pi 2 上运行的 haskell 项目 以及可以使用 raspbian 7 4 1 中的 apt get 安装的 ghc 版本 但它没有 GHCi 这会阻止一些重要的包 如 Vector 的编译 我看
  • Haskell:对 Num 类型类的使用感到困惑

    我很困惑为什么这有效 f Num a gt a gt a f x x 42 但这并没有 g Num a gt a gt a g x x 4 2 我本来就明白Num包含实现运算符的所有类型 因此 如果42 is an Int and 4 2
  • Haskell 中的所有内容都存储在 thunk 中吗,甚至是简单的值?

    以下值 表达式 函数的 thunk 在 Haskell 堆中是什么样子的 val 5 is val a pointer to a box containing 5 add x y x y result add 2 val main prin
  • 我可以从 GHCi 中找到 GHC 版本吗?

    gt 我在里面输入什么GHCi发现它正在使用哪个 GHC 版本 gt import System Info gt browse arch String compilerName String compilerVersion Data Ver
  • 由于垃圾收集,Haskell 程序中会出现多长时间的暂停?

    关于我的另一个问题Haskell 集合可以保证每个操作的最坏情况范围 https stackoverflow com q 12393104 1333025 我很好奇 垃圾收集会导致多长时间的暂停 Haskell 是否使用某种增量垃圾收集 以
  • Haskell / cabal 包的解决方法受到 Nix 和 Cabal 的限制?

    我最近开始开发反射平台 https github com reflex frp reflex platform 有一些额外的配置类似于优秀的反射项目骨架 https github com ElvishJerricco reflex proj
  • 使用默认值压缩而不是删除值?

    我正在 haskell 中寻找一个函数来压缩两个长度可能不同的列表 我能找到的所有 zip 函数都只是删除列表中比其他列表长的所有值 例如 在我的练习中 我有两个示例列表 如果第一个比第二个短 我必须用 0 填充 否则我必须使用 1 我不允
  • Haskell 为替代的 Either 数据类型定义 Functor 实例

    通过 Typeclassopedia 获得一些使用类型类的路由 想要替代Either的一个实例Functor 但即使检查定义Either作为一个例子Functor总是给我带来麻烦 有这个 但不会编译 data Alt a b Success

随机推荐

  • Unity 中的 NuGet 包

    我想在 Unity 中使用一些 NuGet 包 我根据这篇文章实现了Unity找到下载的DLL https www what c ould possible go wrong com unity and nuget https www wh
  • 仅从类层次结构中检索超类

    我有一个场景如下 Entity Table name ANIMAL Inheritance strategy InheritanceType JOINED public class Animal implements Serializabl
  • 有没有办法用一种类型声明多个函数参数?

    我对编程很陌生 无法真正理解为什么我不能只声明参数 类型与我处理普通变量的方式相同 并且必须一次又一次地声明类型 我的意思是 为什么我必须 Func int a int b float c 代替 Func int a b float c 当
  • 如何将 Syntastic 设置为 python3 检查器而不是 python2

    在 MacVim 中 我将以下代码保存为 test py print Hello world python2 这对于 python3 来说显然是错误的 但是 我运行 w 保存文件后 没有错误消息 以下是 vimrc 的一部分 都是关于 Sy
  • 如何在 Xamarin.android 中更改输入光标颜色

    在我的应用程序中需要更改 xamarin android 条目默认颜色 在我的应用程序中 背景图像是黑色 xamarin android 中条目的默认颜色也是相同的颜色 因此需要设置不同的颜色 请就此提出任何想法 我正在尝试以下代码 但没有
  • 在 Azure 自动化 Runbook 中执行时 Set-AzureRmContext 错误

    Update 似乎其他人也遇到了同样的问题reported https feedback azure com forums 246290 automation suggestions 16304161 add azurermaccount
  • 如何将 .sql 文件加载到 Scala?

    我有一个很长的 SQL 查询存储在 data sql 文件中 我想在我的 Scala 代码中执行这个文件 对于 sqlQuery 字符串 我使用 Spark sql sqlQuery 来执行 sql 但是对于 sql 文件 我应该如何执行它
  • 如何制作倒置的边框半径(反应本机)?

    我怎样才能在react native中做出这样的形状 在CSS中 解决方案之一是使用 webkit mask image 但我不知道如何在react native中做到这一点 倒边界半径 https i stack imgur com Yj
  • Realm Cocoa:通过 PK 查找多个对象

    潜伏已久 第一次提问 我在一个项目中使用 Realm Cocoa 来自 Realm io 并且正在努力通过 PK 执行搜索 假设我有一个名为RLMFoo它有一个主键称为bar 我还有一个 PK 列表 假设存储在一个数组中 NSArray p
  • 面试题:在php中,是123==0123吗?

    我已经回答了 这是假的 然后他问为什么 我无法回答 有人能回答吗 我很有兴趣学习它 这段代码 var dump 123 var dump 0123 会给你 int 123 int 83 这是因为0123是八进制表示法 因为0在开始时 whi
  • Erlang 和 JavaScript MD5 摘要匹配

    在这里测试 MD5 的 Javascript 实现 http www webtoolkit info javascript md5 htmlhttp www webtoolkit info javascript md5 html http
  • 分布式深度优先搜索

    我尝试在 C 中实现深度优先搜索 但我不太确定如何以分布式计算方式执行此操作 如果你们能帮我解决这个问题 我将非常感激 你可以在下面找到我的 DFS 代码 public class DFS static List
  • 在react-router :id中使用百分号(%)

    我正在尝试在react router id 中使用百分号 当使用 在 URI 中被禁止 我必须手动编码我的 URI 才能使用这个百分号 因此 使用 Link 时 我使用encodeURI 函数对 URI 进行编码 在我的页面的源代码中 我可
  • onLongPress 未按预期工作

    我有一个表面视图 使用以下代码在其上实现手势检测 surfaceview setOnTouchListener new OnSwipeTouchListener this public class OnSwipeTouchListener
  • 如果 div 为空,则忽略边距

    我有 2 个 DIV 彼此相邻水平对齐 并使用包装器居中 我使用 margin right 将 DIV2 与 DIV1 分开 DIV2 可能没有内容 如果 DIV2 没有内容 我希望忽略边距 而 DIV1 单独居中 这是我的CSS div1
  • 无法找到“org.springframework.mail.javamail.JavaMailSender”类型的 bean

    我在用spring boot 2 0 7 Release and spring boot starter mail 2 0 7 Release 我正在自动装配javaMailsender在尝试部署时 在 Windows 上工作正常的类内部U
  • 如何在 C#.NET 4.0 中编写 WMI 提供程序?

    任何人都可以帮助我使用 C net 4 0 编写电池的 WMI 提供程序吗 有一个旧的 C 示例here http www c sharpcorner com uploadfile falkor wmiproviderguide112620
  • Python 用户定义的数据类型

    我正在用 Python 编写一个 Rogue like 游戏 并定义我的Tile班级 瓷砖可以是块状的 墙壁的或地板的 我希望能够写一些类似的东西 self state Blocked 类似于如何使用布尔值 但具有三个值 有没有一种好方法可
  • 更改 Android 录音默认输入源

    我目前正在编写一个需要录制和实时处理音频数据的应用程序 为此 我使用 AudioRecord 类 这一切都很好 除了我的主要测试设备 Galaxy Nexus 上录制音频的默认设置是从后置扬声器录制 我假设大多数手机的默认录音源是背面或底部
  • GHC 中自动专业化的传递性

    From the docs http www haskell org ghc docs 7 6 3 html users guide pragmas html idp49866112对于 GHC 7 6 你 通常甚至一开始就不需要 SPEC