仍在Haskell的SHA1實現中工作。現在我有一個工作的實施,這是內部循環:優化Haskell內循環
iterateBlock' :: Int -> [Word32] -> Word32 -> Word32 -> Word32 -> Word32 -> Word32 -> [Word32]
iterateBlock' 80 ws a b c d e = [a, b, c, d, e]
iterateBlock' t (w:ws) a b c d e = iterateBlock' (t+1) ws a' b' c' d' e'
where
a' = rotate a 5 + f t b c d + e + w + k t
b' = a
c' = rotate b 30
d' = c
e' = d
探查告訴我,這個函數需要我的實現的運行時間的1/3。我可以想象沒有辦法進一步優化它,除了可能內聯臨時變量,但我相信-O2無論如何會爲我做到這一點。
任何人都可以看到可以進一步應用的重要優化?
僅供參考k和f調用低於。他們非常簡單,我認爲沒有辦法優化這些。除非Data.Bits模塊很慢?
f :: Int -> Word32 -> Word32 -> Word32 -> Word32
f t b c d
| t <= 19 = (b .&. c) .|. ((complement b) .&. d)
| t <= 39 = b `xor` c `xor` d
| t <= 59 = (b .&. c) .|. (b .&. d) .|. (c .&. d)
| otherwise = b `xor` c `xor` d
k :: Int -> Word32
k t
| t <= 19 = 0x5A827999
| t <= 39 = 0x6ED9EBA1
| t <= 59 = 0x8F1BBCDC
| otherwise = 0xCA62C1D6
沒有嘗試,我猜很多問題是保持您的塊數據列表(太多點/內存流量)。我會努力轉移到「Word32」的一個未裝箱的向量,並手動展開循環。除此之外,請用一個嚴格/不包裝的結構來保存'a','b','c','d'和'e';那麼你只有一個需要通過的變量(並且你一定會在上面放置一個爆炸模式,對吧?)。 –
我也會嘗試用表格查找替換所有'(<=)',但我不確定它會有多大幫助。 –
另一件事:在C中編寫嚴格的算術函數並使用FFI調用它通常是一個好主意。如果您小心地引入無副作用,運行時可以使用快速調用C語言來提供良好的性能。 – fuz