5

我试图弄清楚如何优化一些代码。这里是:


{-# OPTIONS_GHC -funbox-strict-fields #-}

data Vec3 a = Vec3  !a !a !a

vx :: Vec3 a -> a
vx (Vec3 x _ _) = x
{-# SPECIALIZE INLINE vx :: Vec3 Double -> Double #-}

vy :: Vec3 a -> a
vy (Vec3 _ y _) = y
{-# SPECIALIZE INLINE vy :: Vec3 Double -> Double #-}

vz :: Vec3 a -> a
vz (Vec3 _ _ z) = z
{-# SPECIALIZE INLINE vz :: Vec3 Double -> Double #-}


dot :: (Num a) => Vec3 a -> Vec3 a -> a
dot u v = (vx u * vx v) + (vy u * vy v) + (vz u * vz v)
{-# SPECIALIZE INLINE dot :: Vec3 Double -> Vec3 Double -> Double #-}


type Vec3D = Vec3 Double

-- just make a bunch of vecs to measure performance

n = 1000000 :: Double

v1s = [Vec3 x y z | (x, y, z) <- zip3 [1 .. n] [2 .. n + 1] [3 .. n + 2]]
      :: [Vec3D]

v2s = [Vec3 x y z | (x, y, z) <- zip3 [3 .. n + 2] [2 .. n + 1] [1 .. n]]
      :: [Vec3D]


dots = zipWith dot v1s v2s  :: [Double]    
theMax = maximum dots :: Double
main :: IO ()
main = putStrLn $ "theMax: " ++ show theMax

当我使用 ghc 6.12.1(i486 机器上的 ubuntu linux)编译时

ghc --make -O2 Vec.hs -prof -auto-all -fforce-recomp

并运行

vec +RTS -p

查看 Vec.prof 文件,


COST CENTRE                    MODULE               %time %alloc

v2s                            Main                  30.9   36.5
v1s                            Main                  27.9   31.3
dots                           Main                  27.2   27.0
CAF                            GHC.Float              4.4    5.2
vy                             Main                   3.7    0.0
vx                             Main                   2.9    0.0
theMax                         Main                   2.2    0.0

我看到函数 vx 和 vy 占用了很大一部分时间。

这是为什么?我认为 SPECIALIZE INLINE 杂注会使这些功能消失。

使用非多态时

data Vec3D = Vec3D {vx, vy, vz :: !Double} deriving Show

函数 vx、vy、vz 不显示为成本中心。

4

2 回答 2

2

我怀疑这是 using 的副作用-auto-all,它抑制了 GHC 通常会执行的许多优化,包括内联。我怀疑您的非多态版本的差异实际上是由于vx, vy, 和vz是通过记录语法定义的,而不是因为多态性(但我对此可能是错误的)。

尝试将导出列表添加到模块并使用“-auto”进行编译,或者通过 SCC pragma 手动设置成本中心,而不是使用 -auto-all。无论如何,我通常都使用 SCC 编译指示,因为我经常想在 let-bound 函数上设置它们,而 -auto-all 不会这样做。

于 2011-01-13T13:48:11.370 回答
2

我不知道如何对回复发表评论,所以我在这个答案中发表评论。

首先,感谢您的回答。

FUZxxl:我尝试了 -ddump-core,但收到一条错误消息,指出 -ddump-core 是一个无法识别的标志。也许您的意思是 -ddump-simpl,Real World Haskell 建议使用该书,但恐怕我不知道如何阅读输出。我在输出文件中查看了“vx”等,但从未见过它们。我想我应该学习如何阅读核心。有什么好的指南吗?

John:根据 GHC 的标志参考文档,如果我没看错的话,-auto 和 -auto-all 都应该将 _scc_s 添加到标记为 INLINE 的函数中。为了查看 -auto 是否对我有用,我创建了另一个测试用例,其中 Vec3 代码位于单独的文件/模块中,并导出了 Vec3(Vec3)、vx、vy、vz 和 dot。我将此模块导入到 Main.hs 文件中。用 -auto 编译这些,我仍然在 .prof 文件中看到了 vx、vy、vz。

回复:您的评论认为差异可能是由于记录语法而不是多态性,我认为差异更可能是由于多态性,因为当我定义

data Vec3 a = Vec3 {vx, vy, vz :: !a}

vx、vy 和 vz 仍然出现在 .prof 文件中。

泰德

于 2011-01-14T07:14:02.910 回答