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

-auto-allこれは、インライン化を含む、GHC が通常実行する多くの最適化を阻害するを使用することの副作用であると思われます。あなたの非ポリモーフィック バージョンの違いは、実際にはvxvyポリモーフィズムvzではなく、レコード構文を介して定義されているためだと思われます (ただし、これについては間違っている可能性があります)。

-auto-all を使用する代わりに、エクスポート リストをモジュールに追加して「-auto」でコンパイルするか、SCC プラグマを介して手動でコスト センターを設定してみてください。私はしばしば SCC プラグマを let バインドされた関数に設定したいので、通常は SCC プラグマを使用しますが、これは -auto-all では実行できません。

于 2011-01-13T13:48:11.370 に答える
2

返信にコメントを付ける方法がわからなかったので、この回答にコメントを付けています。

まず、あなたの答えに感謝します。

FUZxxl: -ddump-core を試したところ、-ddump-core が認識されないフラグであるというエラー メッセージが表示されました。おそらく、Real World Haskell の本が使用を推奨している -ddump-simpl を意味していたのでしょうが、残念ながら出力の読み方がわかりません。「vx」などの出力ファイルを調べましたが、見当たりませんでした。コアの読み方を学ぶべきだと思います。そのための良いガイドはありますか?

John: GHC のフラグ リファレンス ドキュメントによると、正しく読んでいれば、-auto と -auto-all の両方で、 INLINE とマークされていない関数に _scc_s を追加することになっています。-auto が機能するかどうかを確認するために、Vec3 コードが別のファイル/モジュールにあり、Vec3(Vec3)、vx、vy、vz、およびドットがエクスポートされた別のテスト ケースを作成しました。このモジュールを Main.hs ファイルにインポートしました。これらを -auto でコンパイルしても、.prof ファイルに vx、vy、vz が残っています。

Re: 違いはポリモーフィズムではなくレコード構文によるものである可能性があるというあなたのコメント。

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

vx、vy、および vz は引き続き .prof ファイルに表示されます。

少し

于 2011-01-14T07:14:02.910 に答える