haskell - 截断为 Word 类型

标签 haskell

以下代码截断了一些类型 Double类型中的一个 Word16 (虽然我怀疑任何其他单词类型的行为类似,但我不得不为示例选择一个)。

truncate1 :: Double -> Word16
truncate1 = fromIntegral . (truncate :: Double -> Int)

如您所见,我首先将其截断为 Int然后我才将其转换为 Word16 .我将此函数与直接截断进行了基准测试:
truncate2 :: Double -> Word16
truncate2 = truncate

令我惊讶的是,第一个版本(首先通过 Int 类型)的性能要好得多。或者第二个更糟。根据标准输出:
benchmarking truncate/truncate1
mean: 25.42399 ns, lb -47.40484 ps, ub 67.87578 ns, ci 0.950
std dev: 145.5661 ns, lb 84.90195 ns, ub 244.2057 ns, ci 0.950
found 197 outliers among 100 samples (197.0%)
  97 (97.0%) low severe
  100 (100.0%) high severe
variance introduced by outliers: 99.000%
variance is severely inflated by outliers

benchmarking truncate/truncate2
mean: 781.0604 ns, lb 509.3264 ns, ub 1.086767 us, ci 0.950
std dev: 1.436660 us, lb 1.218997 us, ub 1.592479 us, ci 0.950
found 177 outliers among 100 samples (177.0%)
  77 (77.0%) low severe
  100 (100.0%) high severe
variance introduced by outliers: 98.995%
variance is severely inflated by outliers

老实说,我刚开始使用 Criterion,所以我不是使用它的专家,但我了解 25.42399 ns781.0604 ns 更短的执行时间.我怀疑某些特化在这里发挥了作用。是truncate2太慢了?既然如此,可以truncate得到改善?此外,有人知道更快的方法吗?我觉得对我不真正使用的类型进行了错误的转换。

提前致谢。

我正在使用 GHC-7.4.2 进行编译,启用了优化 (-O2)。

最佳答案

首先,注意模块 GHC.Word includes the following RULE语用:

"truncate/Double->Word16"
    forall x. truncate (x :: Double) = (fromIntegral :: Int -> Word16) (truncate x)

这是一个简单的重写规则,可以精确地执行您的truncate1 的优化。提供。所以我们有几个问题需要考虑:

为什么这是一个优化?

因为 truncate 的默认实现是通用的,支持任何 Integral实例。您看到的速度差异是这种普遍性的成本;在将一种原始类型截断为另一种的特定情况下,有更快的方法可用。

所以看来truncate1受益于特殊形式,而 truncate2不是。

为什么是 truncate1快点?

In GHC.Float ,其中 RealFrac Double 的实例已定义,我们有以下 RULE语用:
"truncate/Double->Int"              truncate = double2Int

在哪里 double2Int是我们想要的优化形式。将此与 RULE 进行比较前面提到过——显然没有类似的原始操作专门用于转换 DoubleWord16 .

为什么不 truncate2也被重写?

Quoth the GHC User's Guide:

GHC currently uses a very simple, syntactic, matching algorithm for matching a rule LHS with an expression. It seeks a substitution which makes the LHS and expression syntactically equal modulo alpha conversion. The pattern (rule), but not the expression, is eta-expanded if necessary.



被匹配的表达式不是 eta 扩展的,也就是说在 forall x. foo x 上匹配的规则将匹配 bar y = foo y但不在 bar = foo 中.

由于您的定义都是无意义的,RULE对于 Double -> Int匹配,但 RULE对于 Double -> Word16才不是。

关于haskell - 截断为 Word 类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14820699/

相关文章:

haskell - 模式匹配 Data.Sequence 类似列表

haskell - 如何通过显式类型量化来定义数据类型?

haskell - Happstack 显示一个读取的文件

haskell - 表示有限(非递归)代数类型值的最有效方法是什么?

haskell - 映射到 RankNTypes 函数

Haskell 的 inline-C 可以将 typedef 返回到函数指针吗?

haskell - 如何调用同一个函数 'n'次?

exception - 重新抛出一些异常

haskell - 使用 IO 和状态 monad 进行递归

haskell - 是否有 “dual”用于缩放?