【问题标题】:Fusion optimization with intermediate values具有中间值的融合优化
【发布时间】:2012-12-31 02:53:14
【问题描述】:

GHC 转换具有中间值的表达式的效率是否与没有转换的一样有效?

例如

main = print $ f ["aa", "bb", "cc"]

f x = 
   let a = map (map toUpper) x
       b = filter (\z -> 'C' /= head z) a
       c = foldl1 (++) b
   in c

似乎有非常不同的核心输出(-ddump-simple)与

f x = foldl1 (++) $ filter (\z -> 'C' /= head z) $ map (map toUpper) x

具有中间值的表达式是否需要(显着)更长的时间来计算?

【问题讨论】:

  • 请注意,这是使用 build/foldr 融合,因为您使用的是默认的 GHC 列表实现。如果您想要流版本,请使用 stream-fusion 包。好处是 foldl1 融合了。
  • 两个版本都为我提供了相同的内核,分别为 7.6.1 和 7.2.2(使用 -O-O2)。您使用了哪些版本和优化标志?
  • @DanielFischer:我没有使用任何优化标志;我想知道的是“这些是什么时候不等价的”,看起来答案是“不使用优化标志的时候”。
  • @amindfv 没有优化基本上意味着“音译已写的内容”。这绝不是一个好主意。
  • 不开启优化,重写规则优化将不会开启。

标签: performance haskell optimization ghc


【解决方案1】:

中间let 绑定的线性使用相当于将(.) 放在值之间。

GHC 将通过这些管道进行融合。从-ddump-simpl-stats的结果可以看到

使用 let 绑定:

15 RuleFired
    1 ++
    1 Class op /=
    1 Class op show
    1 Class op showList
    1 filter
    1 fold/build
    1 foldr/app
    1 map
    1 neChar#->case
    3 unpack
    3 unpack-list

使用管道:

15 RuleFired
    1 ++
    1 Class op /=
    1 Class op show
    1 Class op showList
    1 filter
    1 fold/build
    1 foldr/app
    1 map
    1 neChar#->case
    3 unpack
    3 unpack-list

还有同一个 fused worker:

使用 let 绑定:

Main.main_go =
  \ (ds_aAz :: [[GHC.Types.Char]]) ->
    case ds_aAz of _ {
      [] -> GHC.Types.[] @ [GHC.Types.Char];
      : y_aAE ys_aAF ->
        case GHC.Base.map
               @ GHC.Types.Char @ GHC.Types.Char GHC.Unicode.toUpper y_aAE
        of wild1_azI {
          [] ->
            GHC.List.badHead
            `cast` (UnsafeCo (forall a_azK. a_azK) [[GHC.Types.Char]]
                    :: (forall a_azK. a_azK) ~ [[GHC.Types.Char]]);
          : x_azM ds1_azN ->
            case x_azM of _ { GHC.Types.C# c2_aAa ->
            case c2_aAa of _ {
              __DEFAULT ->
                GHC.Types.: @ [GHC.Types.Char] wild1_azI (Main.main_go ys_aAF);
              'C' -> Main.main_go ys_aAF
            }

管道:

Main.main_go =
  \ (ds_aAA :: [[GHC.Types.Char]]) ->
    case ds_aAA of _ {
      [] -> GHC.Types.[] @ [GHC.Types.Char];
      : y_aAF ys_aAG ->
        case GHC.Base.map
               @ GHC.Types.Char @ GHC.Types.Char GHC.Unicode.toUpper y_aAF
        of wild1_azB {
          [] ->
            GHC.List.badHead
            `cast` (UnsafeCo (forall a_azD. a_azD) [[GHC.Types.Char]]
                    :: (forall a_azD. a_azD) ~ [[GHC.Types.Char]]);
          : x_azF ds1_azG ->
            case x_azF of _ { GHC.Types.C# c2_aA3 ->
            case c2_aA3 of _ {
              __DEFAULT ->
                GHC.Types.: @ [GHC.Types.Char] wild1_azB (Main.main_go ys_aAG);
              'C' -> Main.main_go ys_aAG
            }
            }

你忘了用 -O2 编译吗?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-17
    • 2015-02-21
    • 2014-01-03
    • 2018-06-18
    • 1970-01-01
    • 2013-04-20
    • 1970-01-01
    相关资源
    最近更新 更多