Haskell模块优化

vve*_*bik 6 optimization haskell

我有Haskell模块优化的问题.

有主模块.

{-# LANGUAGE OverloadedStrings #-}
module Main where

import Control.DeepSeq
import Formatting
import Formatting.Clock
import System.Clock

import Data.Array

size :: Int
size = 200 :: Int

stdMult     :: (Ix a, Ix b, Ix c, Num d) =>
               Array (a,b) d -> Array (b,c) d -> Array (a,c) d
stdMult x y =  array resultBounds
                 [((i,j), sum [ x!(i,k) * y!(k,j) | k <- range (lj,uj)])
                                   | i <- range (li,ui),
                                     j <- range (lj',uj') ]
    where ((li,lj),(ui,uj))     = bounds x
          ((li',lj'),(ui',uj')) = bounds y
          resultBounds
            | (lj,uj)==(li',ui') = ((li,lj'),(ui,uj'))
            | otherwise = error "error"


main :: IO ()
main = do
  let a = array ((1,1),(size, size)) [((i,j), 2*i-j) |
                                  i <- range (1,size),
                                  j <- range (1,size)]
  let b = array ((1,1),(size, size)) [((i,j), 2*i+3*j) |
                                  i <- range (1,size)`,
                                  j <- range (1,size)]

  start <- getTime ProcessCPUTime
  let
    c = stdMult a b
  end <- c `deepseq` getTime ProcessCPUTime
  fprint (timeSpecs % "\n") start end
  return()
Run Code Online (Sandbox Code Playgroud)

stdMult主模块中,一切工作正常.我换成stdMult另一个模块.当我不使用ghc优化时,执行时间是相同的.当我使用ghc选项-O3时,stdMult在主模块中执行时间减少,但stdMult在另一个模块中,执行时间几乎不变!例如,当stdMult在Main中我有时间3秒,而当stdMult不在Main时我有时间30秒,对于矩阵500x500.

这很奇怪!

Cla*_*ude 10

(您需要Hackage中的clockformatting包来编译代码.)

当我stdMult在不同的模块中时,我可以重现10倍减速.幸运的是,修复很容易:在stdMult定义的模块中,添加一个INLINABLEpragma:

{-# INLINABLE stdMult #-}
Run Code Online (Sandbox Code Playgroud)

它将定义添加到接口文件(.hi)中,允许在使用它的模块中进行内联,这反过来允许它专门用于快速机器Int而不是慢速抽象IxNum多态代码.(如果它在同一模块中,GHC可以随意内联和专门化,并且事情不是INLINABLE默认的,因为它可能导致可执行代码膨胀和较慢的编译.)

或者INLINABLE,您可以手动SPECIALIZE选择要优化实现的类型.这有点冗长,但在大型项目中编译应该更快(每次导出一次,而不是每次导入一次,粗略猜测).

{-# SPECIALIZE stdMult :: Array (Int, Int) Int -> Array (Int, Int) Int -> Array (Int, Int) Int #-}
Run Code Online (Sandbox Code Playgroud)