Je suis en train de travailler sur une mise en œuvre de l'un des SHA3 candidats, JH. J'en suis au point où l'algorithme de passer tous les KATs (Réponse Connue Tests) fournies par le NIST, et ont également une instance de la Crypto-API. Ainsi, j'ai commencé à chercher dans ses performances. Mais je suis assez nouveau à Haskell et ne savez pas vraiment ce qu'il faut rechercher lors de l'analyse.
Pour le moment mon code est toujours plus lent que l'implémentation de référence écrit en C, par un facteur de 10 pour toutes les longueurs d'entrée (C code trouvé ici: http://www3.ntu.edu.sg/home/wuhj/research/jh/jh_bitslice_ref64.h).
Mon code Haskell se trouve ici: https://github.com/hakoja/SHA3/blob/master/Data/Digest/JHInternal.hs.
Maintenant, je ne vous attendez pas à parcourir tout mon code, mais je voudrais juste vous souhaitez quelques conseils sur un couple de fonctions. J'ai couru quelques tests de performance et c'est (une partie de) la performance de fichier généré par GHC:
Tue Oct 25 19:01 2011 Time and Allocation Profiling Report (Final)
main +RTS -sstderr -p -hc -RTS jh e False
total time = 6.56 secs (328 ticks @ 20 ms)
total alloc = 4,086,951,472 bytes (excludes profiling overheads)
COST CENTRE MODULE %time %alloc
roundFunction Data.Digest.JHInternal 28.4 37.4
word128Shift Data.BigWord.Word128 14.9 19.7
blockMap Data.Digest.JHInternal 11.9 12.9
getBytes Data.Serialize.Get 6.7 2.4
unGet Data.Serialize.Get 5.5 1.3
sbox Data.Digest.JHInternal 4.0 7.4
getWord64be Data.Serialize.Get 3.7 1.6
e8 Data.Digest.JHInternal 3.7 0.0
swap4 Data.Digest.JHInternal 3.0 0.7
swap16 Data.Digest.JHInternal 3.0 0.7
swap8 Data.Digest.JHInternal 1.8 0.7
swap32 Data.Digest.JHInternal 1.8 0.7
parseBlock Data.Digest.JHInternal 1.8 1.2
swap2 Data.Digest.JHInternal 1.5 0.7
swap1 Data.Digest.JHInternal 1.5 0.7
linearTransform Data.Digest.JHInternal 1.5 8.6
shiftl_w64 Data.Serialize.Get 1.2 1.1
Detailed breakdown omitted ...
Maintenant, rapidement, sur le JH algorithme:
C'est un algorithme de hachage qui se compose d'une fonction de compression F8, qui est répétée tant qu'il existe des blocs d'entrées (de 512 bits). C'est juste la façon dont le SHA-les fonctions opèrent. La touche F8 fonction consiste en la E8 fonction qui applique une fonction à 42 reprises. La ronde de la fonction elle-même se compose de trois parties: une sbox, une transformation linéaire et d'une permutation ("swap dans mon code).
Par conséquent, il est raisonnable que la plupart du temps est passé dans la fonction arrondi. Je voudrais savoir comment les parties pourraient être améliorés. Par exemple: le blockMap fonction est une fonction d'utilité, la cartographie d'une fonction sur les éléments dans un 4-tuple. Alors pourquoi est-il effectuer si mal? Toute suggestion serait la bienvenue, et pas seulement sur la seule les fonctions, c'est à dire sont là des changements structurels que vous auriez fait dans le but d'améliorer les performances?
J'ai essayé de chercher au Cœur de sortie, mais malheureusement c'est au dessus de ma tête.
J'attache des tas de profils à la fin aussi bien dans le cas qui pourraient être d'intérêt.
EDIT :
J'ai oublié de mentionner mon installation et de construction. Je l'exécute sur un x86_64 Arch Linux de la machine, GHC 7.0.3-2 (je crois), avec des options de compilation:
ghc --make-O2 -funbox-strict-champs
Malheureusement, il semble y avoir un bug sur le Linux plattform lors de la compilation via C ou LLVM, ce qui me donne l'erreur:
Erreur: .la taille de l'expression de XXXX ne pas évaluer à une constante
donc je n'ai pas été en mesure de voir l'effet de cette.