Todavía estoy trabajando en mi implementación de SHA1 en Haskell. ahora tengo una implementación funcional y este es el bucle interno:Optimización de Haskell Inner Loops
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
El perfilador me dice que esta función toma un tercio del tiempo de ejecución de mi aplicación. No puedo pensar en otra forma de optimizarlo más allá de tal vez incluir las variables temporales, pero creo que O2 hará eso por mí de todos modos.
¿Alguien puede ver una optimización significativa que se puede aplicar aún más?
FYI las llamadas k y f están a continuación. Son tan simples que no creo que haya una forma de optimizar estos otros. A menos que el módulo Data.Bits sea lento
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
Sin intentarlo, supongo que gran parte del problema es mantener sus datos de bloque en una lista (demasiado tráfico de punto/memoria). Intentaría moverme a un vector no empaquetado de 'Word32' y desenrollar manualmente el ciclo. A falta de eso, pruébelo con una estructura estricta/sin empaquetar que contenga 'a',' b', 'c',' d', y 'e'; entonces solo tendrías que pasar una variable (y estarías seguro de ponerle un patrón de explosión, ¿no?). –
También trataría de reemplazar todo el '(<=)' con una tabla de búsqueda, aunque no estoy seguro de que sea de mucha ayuda. –
Otra cosa: a menudo es una buena idea escribir funciones aritméticas ajustadas en C y llamarlas usando el FFI. Si tiene cuidado de no presentar efectos secundarios, el tiempo de ejecución puede usar una llamada rápida a C que le da un buen rendimiento. – fuz