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中的clock和formatting包来编译代码.)
当我stdMult在不同的模块中时,我可以重现10倍减速.幸运的是,修复很容易:在stdMult定义的模块中,添加一个INLINABLEpragma:
{-# INLINABLE stdMult #-}
Run Code Online (Sandbox Code Playgroud)
它将定义添加到接口文件(.hi)中,允许在使用它的模块中进行内联,这反过来允许它专门用于快速机器Int而不是慢速抽象Ix和Num多态代码.(如果它在同一模块中,GHC可以随意内联和专门化,并且事情不是INLINABLE默认的,因为它可能导致可执行代码膨胀和较慢的编译.)
或者INLINABLE,您可以手动SPECIALIZE选择要优化实现的类型.这有点冗长,但在大型项目中编译应该更快(每次导出一次,而不是每次导入一次,粗略猜测).
{-# SPECIALIZE stdMult :: Array (Int, Int) Int -> Array (Int, Int) Int -> Array (Int, Int) Int #-}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
152 次 |
| 最近记录: |