まだ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を取ることを私に伝えます。私は一時変数をインライン展開する以外の方法をそれ以上最適化する方法はないと思うが、私はとにかくそれを行うだろうと私は信じている。
今後さらに適用できる重要な最適化を誰も見ることができますか?
FYIの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'の厳密な/アンパック構造で試してみてください。渡す必要のある変数は1つしかありません(その上にバンパターンを必ず配置してください)。 –
'(<=)'をテーブルルックアップに置き換えようとしていますが、それはあまり役に立たないでしょう。 –
別のこと:しばしば、Cでタイトな算術関数を書いて、それをFFIを使って呼び出すことをお勧めします。あなたが副作用を導入しないよう注意しているなら、ランタイムは良いパフォーマンスを与えるCへの高速呼び出しを使用することができます。 – fuz