内联函数仍显示在 .prof 文件中

Posted

技术标签:

【中文标题】内联函数仍显示在 .prof 文件中【英文标题】:inlined functions still show up in the .prof file 【发布时间】:2011-01-13 03:59:49 【问题描述】:

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


-# 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 不显示为成本中心。

【问题讨论】:

你真的看过core吗?尝试使用-ddump-core 进行编译,看看发生了什么。 【参考方案1】:

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

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

【讨论】:

【参考方案2】:

我不知道如何为回复制作 cmets,所以我在这个答案中制作 cmets。

首先,感谢您的回答。

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

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

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

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

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

有点

【讨论】:

您应该考虑使用真实帐户来回答您的问题。如果您有这样的帐户,则可以先对自己的问题发表评论,然后在您的声誉足够高的情况下发表评论。

以上是关于内联函数仍显示在 .prof 文件中的主要内容,如果未能解决你的问题,请参考以下文章

C++ 中的内联函数

如何告诉 gcc 不要内联函数?

链接器可以内联函数吗?

c++中的内联函数inline

.c 文件中的 C99 内联函数

检查内联函数内的变量值