Я работаю над реализацией одного из кандидатов SHA3, JH.Я нахожусь в точке, где алгоритм проходит все KAT (известные тесты ответов), предоставленные NIST, и также сделал его экземпляром Crypto-API.Таким образом, я начал изучать его производительность.Но я совершенно новичок в Haskell и не знаю, на что обращать внимание при профилировании.
В данный момент мой код постоянно медленнее, чем эталонная реализация, написанная на C, с коэффициентом 10 для всех входных длин (код C находится здесь: http://www3.ntu.edu.sg/home/wuhj/research/jh/jh_bitslice_ref64.h).
MyКод на Haskell находится здесь: https://github.com/hakoja/SHA3/blob/master/Data/Digest/JHInternal.hs.
Теперь я не ожидаю, что вы разберетесь со всем моим кодом, скорее, я просто хотел бы получить несколько советов по нескольким функциям. Я запустил некоторую производительностьпроверяет, и это (часть) файла производительности, сгенерированного 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 ...
Теперь быстро об алгоритме JH:
Это алгоритм хеширования, который состоит из функции сжатия F8, котораяповторяется до тех пор, пока существуют входные блоки (длиной 512 бит). Именно так работают функции SHA. Функция F8 состоит из функции E8, которая применяет функцию округления 42 раза. Сама функция округления состоит из трех частей: sbox, линейное преобразование и перестановка (в моем коде это называется swap).
Таким образом, вполне разумно, что большую часть времени проводят в роутере.nd функция.Тем не менее, я хотел бы знать, как можно улучшить эти детали.Например: функция blockMap - это просто служебная функция, отображающая функцию на элементы в четырех кортеже.Так почему же так плохо?Любые предложения будут приветствоваться, и не только по отдельным функциям, то есть, есть ли структурные изменения, которые вы бы сделали, чтобы улучшить производительность?
Я попытался посмотреть на вывод Core, но, к сожалению, это намного выше моегоголова.
Я также прикрепляю некоторые из профилей кучи в конце, если это может быть интересно.
РЕДАКТИРОВАТЬ:
Я забыл упомянутьмои настройки и сборки.Я запускаю его на компьютере x86_64 Arch Linux, GHC 7.0.3-2 (я думаю), с параметрами компиляции:
ghc --make -O2 -funbox-strict-fields
К сожалению , похоже, есть ошибка на платформе Linux при компиляции через C или LLVM, которая выдает мне ошибку:
Ошибка: выражение .size для XXXXне оценивается как постоянная
, поэтому я не смог увидеть эффект этого.
![enter image description here](https://i.stack.imgur.com/LiZwL.png)
![enter image description here](https://i.stack.imgur.com/BJE7W.png)