新しいARM Crypto Extensionだと、中国系のSM3とかSHA3とかSHA512とかの専用命令があるのだけど、Appleは比較的こういうところに投資をしてるので、Appleのチップだと実装されている。
パフォーマンス的な情報はインターネットに転がっていないので、試しに手元で実装してみた。データはいつもの通りのNSSでのデータ。
実装前のデータはこれ。
# mode in opreps cxreps context op time(sec) thrgput sha512_e 1Gb 15M 0 0.000 10000.000 10.000 168Mb
実装するとこうなる
# mode in opreps cxreps context op time(sec) thrgput sha512_e 4Gb 47M 0 0.000 10000.000 10.000 503Mb
SHA1、SHA256と同様に3倍くらい速くなる感じですね。
SHA256とは違って、ROUNDに対するレジスタが足りないので、ext
を使って、利用するベクタを選択しながらループしないといけないのでシンプルにはならない
#define ROUND(n, a, b, c, d, e, f, g, h, w0, w1, w2, w3, w4) \ { \ uint64x2_t t, fg, de; \ t = vaddq_u64(a, vld1q_u64(K512 + n * 2)); \ t = vreinterpretq_u64_u8(vextq_u8(vreinterpretq_u8_u64(t), \ vreinterpretq_u8_u64(t), 8)); \ de = vreinterpretq_u64_u8(vextq_u8(vreinterpretq_u8_u64(w1), \ vreinterpretq_u8_u64(w2), 8)); \ fg = vreinterpretq_u64_u8(vextq_u8(vreinterpretq_u8_u64(w2), \ vreinterpretq_u8_u64(w3), 8)); \ w3 = vaddq_u64(w3, t); \ w3 = vsha512hq_u64(w3, fg, de); \ w4 = vaddq_u64(w1, w3); \ w3 = vsha512h2q_u64(w3, w1, w0); \ if (n < 32) { \ a = vsha512su0q_u64(a, b); \ a = vsha512su1q_u64(a, h, \ vextq_u8(vreinterpretq_u8_u64(e), \ vreinterpretq_u8_u64(f), 8)); \ } \ }
なお、SHA512のIntrinsicsはgccの最新であれば実装されているが、clangの場合は最新のコードでも実装されていないので、インラインアセンブラ使うなりアセンブラで書かないといけない