2012-01-05 207 views
4

我有一個單線函數佔用了我執行時間的25%,這種方式對我來說是非常直觀的。爲什麼這個Haskell函數很慢?

上下文是一個棋盤遊戲(布洛克斯)的AI,特別是我們在這裏做的是試圖確定是否合法地在特定的棋盤單元附近放置棋子。我們已經預先計算了一個Word64(placementBitmap),它顯示了這個單元在特定方向上佔用了哪些單元格,最近我們計算出了一個Word64(cornerBitmap),它顯示了圍繞這個正方形的哪些單元格可用。所以現在我們對它們進行比較:

legalAt (TerritoryCorner _ _ cornerBitmap) (Placement _ _ _ placementBitmap) = (placementBitmap .&. cornerBitmap) == placementBitmap 

我不明白怎麼一對夫婦的位操作的位置可能需要更多的時間比過程來計算擺在首位的cornerBitmap。拳擊問題?我對Haskell很新。

TerritoryCorner和Placement的數據構造函數都是這樣定義的,即最後一個參數是嚴格的,無論值多少。

在此使用的語境是一個列表理解:

[getMyChild corner placement | corner <- myCorners, placement <- myPlacements, legalAt corner placement] 

我設法生產出以下核心,但我不知道如何解釋它:

GameState.legalAt [InlPrag=INLINE[0]] 
    :: Types.TerritoryCorner -> Types.Placement -> GHC.Bool.Bool 
[GblId, 
Arity=2, 
Caf=NoCafRefs, 
Str=DmdType U(AAAL)U(UUUL), 
Unf=Unf{Src=InlineStable, TopLvl=True, Arity=2, Value=True, 
     ConLike=True, Cheap=True, Expandable=True, 
     Guidance=ALWAYS_IF(unsat_ok=True,boring_ok=False) 
     Tmpl= \ (w_soat [Occ=Once!] :: Types.TerritoryCorner) 
       (w1_soaA [Occ=Once!] :: Types.Placement) -> 
       case w_soat of _ { Types.TerritoryCorner _ _ _ ww3_soay -> 
       case w1_soaA of _ { Types.Placement _ _ _ ww7_soaF -> 
       __scc {legalAt main:GameState} 
       case {__pkg_ccall ghc-prim hs_and64 GHC.Prim.Word64# 
           -> GHC.Prim.Word64# 
           -> GHC.Prim.State# GHC.Prim.RealWorld 
           -> (# GHC.Prim.State# GHC.Prim.RealWorld, GHC.Prim.Word64# #)}_aHK 
         ww7_soaF ww3_soay GHC.Prim.realWorld# 
       of _ { (# _, ds3_aHQ [Occ=Once] #) -> 
       GHC.IntWord64.eqWord64# ds3_aHQ ww7_soaF 
       } 
       } 
       }}] 
GameState.legalAt = 
    \ (w_soat :: Types.TerritoryCorner) (w1_soaA :: Types.Placement) -> 
    case w_soat 
    of _ { Types.TerritoryCorner ww_soav ww1_soaw ww2_soax ww3_soay -> 
    case w1_soaA 
    of _ { Types.Placement ww4_soaC ww5_soaD ww6_soaE ww7_soaF -> 
    __scc {legalAt main:GameState} 
    case {__pkg_ccall ghc-prim hs_and64 GHC.Prim.Word64# 
           -> GHC.Prim.Word64# 
           -> GHC.Prim.State# GHC.Prim.RealWorld 
           -> (# GHC.Prim.State# GHC.Prim.RealWorld, GHC.Prim.Word64# #)}_aHK 
      ww7_soaF ww3_soay GHC.Prim.realWorld# 
    of _ { (# _, ds3_aHQ #) -> 
    GHC.IntWord64.eqWord64# ds3_aHQ ww7_soaF 
    } 
    } 
    } 
+2

您是否在32位平臺上? (而且很明顯:用'-O2'編譯?) – ehird 2012-01-05 14:34:06

+0

@ehird是的,(s)他在32位平臺上,並進行了優化編譯,儘管這可能是'-O1' :) – 2012-01-05 14:49:49

+0

@DanielFischer:那我會教我發表我的猜測,而不是回答! :) – ehird 2012-01-05 14:50:38

回答

4

你」在32位平臺上運行,因此64位操作是C調用,這使得它們比64位平臺稍慢。但是,這不應該花費太多,並且legalAt的核心就像人們所希望的那樣好。我認爲與您的看法相反,cornerBitmapplacementBitmap的計算之前沒有完成,並且被legalAt強制執行,並且由剖析器將成本歸因於此。

我們需要查看更多代碼和上下文以瞭解更多信息。

+0

我想我只是誤解函數的調用方式,是的。它可能比我原先想象的要多得多。我想可能這個功能有些問題,對於Haskell知識較好的人來說,這是顯而易見的,但我猜不。我會再看看,稍後再回來 – David 2012-01-05 17:27:28