Ice Lakeプロセッサは整数除算がアツい 数値計算編
下記の前回の記事でIce Lakeプロセッサは整数除算命令が強化されていることが実験を通じてわかった.
ただこの記事では単にidiv命令をただ実行しまくっただけなので,特に意味がない処理をしている.そのため,もう少しだけそれらしい処理をさせて整数除算が強化されているかどうかをもう少しだけ見ていこうと思う.
今回は多倍長整数除算の処理をさせていく.といっても,除数と被除数が共に任意精度の時の除算処理は実装が非常に大変であるため,除数に関しては1ワードのみとし「(多倍長整数) / (1ワード整数)」の計算の処理とした.
実装
以下が簡易的多倍長整数除算の実装である.
(追記:aやbなどはuint32_tで十分というご指摘をいただきました.ありがとうございます.)
void divide(uint32_t *a, uint32_t b, uint64_t len, uint32_t *q, uint32_t r){ int i; uint64_t tmp; for(i=len-1; i>=0; i--){ tmp = (a[i+1] << 32) | a[i]; q[i] = tmp / b; a[i] = tmp % b; } r = a[0]; }
除算は複雑であるがゆえに,「2ワード / 1ワード」というシンプルな除算ですら実装が難しい.したがって簡単のため,「128ビット / 64ビット」ではなく「64ビット / 32ビット」の計算に出来るようにするため,uint64_t変数tmpにuint32_t変数を2つ詰めて計算をすることにした.そのため除算の前にシフト演算等を行なっている.
本実験の主眼はプロセッサの除算命令の演算能力を見ることなので,被除数の配列が壊れてしまうなどの問題点こそあるが,正しく商と剰余が計算できていたのでこれで良しとした.
また以下が実装した除算関数のobjdumpの出力である.下線部のように符号なし除算命令であるdiv命令が実行されることが確認できた.
00000000000009f0 <divide>: for(i=len-1; i>=0; i--){ 9f0: 83 ea 01 sub $0x1,%edx 9f3: 78 2e js a23 <divide+0x33> 9f5: 4c 63 ca movslq %edx,%r9 9f8: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1) 9ff: 00 tmp = (a[i+1] << 32) | a[i]; a00: 4a 8b 44 cf 08 mov 0x8(%rdi,%r9,8),%rax a05: 31 d2 xor %edx,%edx a07: 48 c1 e0 20 shl $0x20,%rax a0b: 4a 0b 04 cf or (%rdi,%r9,8),%rax a0f: 48 f7 f6 div %rsi q[i] = tmp / b; a12: 4a 89 04 c9 mov %rax,(%rcx,%r9,8) a[i] = tmp % b; a16: 4a 89 14 cf mov %rdx,(%rdi,%r9,8) a1a: 49 83 e9 01 sub $0x1,%r9 for(i=alen-1; i>=0; i--){ a1e: 45 85 c9 test %r9d,%r9d a21: 79 dd jns a00 <divide+0x10> } r = a[0]; a23: 48 8b 07 mov (%rdi),%rax a26: 49 89 00 mov %rax,(%r8) } a29: c3 retq a2a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
実験
今回実験に使用したプロセッサは以下の3つである.
- Intel(R) Core(TM) i7-8559U CPU @ 2.70GHz (Coffee Lake)
- Intel(R) Core(TM) i7-7820X CPU @ 3.60GHz (Skylake-X)
- Intel(R) Core(TM) i3-8121U CPU @ 2.20GHz (Cannon Lake)
また被除数のワード数を4096ワードとし,これを3000回実行した.この除算関数を3000回実行した実行時間を取って比較することとした.
実験結果
"Time: ~~ [ms]"が除算関数の総実行時間である.
- Coffee Lake @ 2.70GHz
$ time ./a.out
Time: 114.418000 [ms]
real 0m0.122suser 0m0.115s
sys 0m0.003s
- Skylake@ 3.60GHz
$ time ./a.out
Time: 99.025000 [ms]
real 0m0.102suser 0m0.100s
sys 0m0.000s
- Cannon Lake(実質Ice Lake)@ 2.20GHz
$ time ./a.out
Time: 89.798000 [ms]
real 0m0.094suser 0m0.093s
sys 0m0.000s
動作周波数の観点でいうと「Cannon Lake < Coffee Lake < Skylake」であるが,実行時間の性能の観点では「Coffee Lake < Skylake < Cannon Lake」となった.
したがって除算命令の高速化により,条件付き多倍長整数除算の高速化が見込めることがわかった.
Ice Lakeプロセッサは除算がアツい.