Recommended
PDF
PDF
PPTX
PDF
PPTX
【Unity道場スペシャル 2017博多】クォータニオン完全マスター
PDF
PDF
組み込み関数(intrinsic)によるSIMD入門
PDF
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.
PDF
PDF
PDF
いまさら聞けないarmを使ったNEONの基礎と活用事例
PDF
【Unity道場】AssetGraph入門 〜ノードを駆使しててUnityの面倒な手作業を自動化する方法〜
PDF
PPTX
BoostAsioで可読性を求めるのは間違っているだろうか
PDF
PPTX
画像処理ライブラリ OpenCV で 出来ること・出来ないこと
PPTX
PDF
PDF
PDF
PDF
ARM CPUにおけるSIMDを用いた高速計算入門
PDF
自然言語処理を 役立てるのはなぜ難しいのか(2022/10/25東大大学院「自然言語処理応用」)
PPTX
PDF
PDF
PPTX
PDF
PDF
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
PPTX
PDF
An OpenCL Method of Parallel Sorting Algorithms for GPU Architecture
More Related Content
PDF
PDF
PPTX
PDF
PPTX
【Unity道場スペシャル 2017博多】クォータニオン完全マスター
PDF
PDF
組み込み関数(intrinsic)によるSIMD入門
PDF
Pythonの処理系はどのように実装され,どのように動いているのか? 我々はその実態を調査すべくアマゾンへと飛んだ.
What's hot
PDF
PDF
PDF
いまさら聞けないarmを使ったNEONの基礎と活用事例
PDF
【Unity道場】AssetGraph入門 〜ノードを駆使しててUnityの面倒な手作業を自動化する方法〜
PDF
PPTX
BoostAsioで可読性を求めるのは間違っているだろうか
PDF
PPTX
画像処理ライブラリ OpenCV で 出来ること・出来ないこと
PPTX
PDF
PDF
PDF
PDF
ARM CPUにおけるSIMDを用いた高速計算入門
PDF
自然言語処理を 役立てるのはなぜ難しいのか(2022/10/25東大大学院「自然言語処理応用」)
PPTX
PDF
PDF
PPTX
PDF
PDF
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
Viewers also liked
PPTX
PDF
An OpenCL Method of Parallel Sorting Algorithms for GPU Architecture
PDF
高位合成友の会第四回(2016/11/22)スライド
PPTX
PDF
PPTX
PDF
PDF
PPTX
PDF
PDF
PDF
PDF
PDF
PDF
PDF
PDF
KEY
詳解UNIXプログラミング 第4章 ファイルとディレクトリ
PDF
PDF
【幕張読書会】Unixカーネルの設計 3(バッファキャッシュ)
Similar to SIMDで整数除算
PDF
Javaセキュアコーディングセミナー東京第2回講義
PDF
PDF
PPT
PDF
PDF
PPT
PDF
PPTX
AtCoder Beginner Contest 012 解説
PDF
AtCoder Beginner Contest 010 解説
PDF
PDF
PDF
AtCoder Beginner Contest 020 解説
PDF
PDF
姫路 IT 系勉強会 Vol.6 プログラミングコンテストという名のオンラインゲームがあるらしい
PDF
PDF
PDF
PDF
PPTX
AtCoder Beginner Contest 004 解説
SIMDで整数除算 1. 2. 3. 4. 5. おさらい・浮動小数点数の除算
• 直接除算する方法
– __m128 _mm_div_ps( __m128 a, __m128 b );
• DIVPS xmm1, xmm2 (SSE1)
• 遅い代わりに精度が高い
– スループットは1/20、遅すぎ
• 逆数を求めて乗算にする方法
– __m128 _mm_rcp_ps( __m128 a );
• RCPPS xmm1, xmm2 (SSE1)
• 速い代わりに精度が低い
– その後乗算も必要
(´・ω・`)Shobomaru 5
6. 7. 整数の除算
• 除算命令
– ない…
• 逆数命令
– ない…
• 右シフト命令
– 2の冪乗でしか使えない
• ⇒ なんとか自分で逆数を求めるしかない
– でも逆数は1以下なので、整数では表現できない…
(´・ω・`)Shobomaru 7
8. 整数を固定小数として扱う
• 最上位ビット(MSB)が0.5、MSBの隣が0.25、
その隣が0.125…
• 例:“0.2”
– = 0.125 + 0.0625 + 0.00078125 + 0.000390625 + …
– 2進数表現では(とりえず16bitで)
“0.0011001100110011”
– 小数点以下を固定小数として取り出す
“13037”
– 固定小数なので、2^16である“65536”が1を表す
• 13037÷65536=0.199996948242188≒0.2
(´・ω・`)Shobomaru 8
9. 固定小数の掛け算
• 例:“8÷5”
– = 8×13037÷65536
• この除算は16bit論理右シフトで代用可能
“(8*13037) >> 16”
– = 1.5999755859375
– 整数でキャストして答えは“1”
_,,-―=''' ̄ ___,,-―――='' ̄ __,-―='' ̄ /
_,,-―=''' ̄ _,,-―='' ̄ ヽ / +
 ̄ ̄ _,,-―=''' ̄ \ / . . . .
,,-='' ̄ _ノ ,_ノ ヽ / . 。. ★ ☆
,,,-'' / iニ)ヽ, /rj:ヽヽ ヽ/ 。. .
-―'' ̄ ;〈 !:::::::c! |___,/' {.::::::;、! } | -┼- 丿~~~| |~~~~~| __ ■
. |. (つ`''" | / `'ー''(つ. |. -┼- /~~~~/ 丿 | 丿 ▼ ▼
| . ///// | / /// | | 丿 / 丿 ● ●
ヽ γ´~⌒ヽ. | / /
――ヽ / ヽ | / /⌒ヽ、
\/ | |_/ / ヽ
(´・ω・`)Shobomaru 9
10. 精度の問題
• この方法で“10÷5”を計算すると…
– 10×13037÷65536
– = 1.99996948242188
– 整数でキャストして“1”…???
,,-―=''' ̄ ___,,-―――='' ̄ __,-―='' ̄ /
_,,-―=''' ̄ _,,-―='' ̄ ヽ / +
 ̄ ̄ _,,-―=''' ̄ \ / . . . .
,,-='' ̄ _ノ ,_ノ ヽ / . 。. ★ ☆
,,,-'' / iニ)ヽ, /rj:ヽヽ ヽ/ 。. .
-―'' ̄ ;〈 !:::::::c! ' {.::::::;、! 〉 |  ̄ ̄| _|_ 丿 |~~~~~|
. | (つ`''" __ `'ー''(つ | | | /|. 丿 | 丿
| ///// | | /// | __| 丿 | / 丿
ヽ γ´~⌒ヽ. / | /
――ヽ / ヽ / | /⌒ヽ、
\/ | | ̄ ̄ ̄ ̄| / ヽ
• なぜ?
– 逆数の丸め誤差を考慮していないから
(´・ω・`)Shobomaru 10
11. Terje Mathisenのアルゴリズム(?) [1]
• 逆数の小数点の位置をできるだけ右にずらす
– 代償として、乗算後の論理右シフトの量を調整する
xを割られる数、dを割る数とするとき、
b = (有効ビット数) – 1
r=w+b
f = 2r / d
もしfが整数ならば、case Aへ
もしfの小数部が0.5未満ならば、case Bへ
もしfの小数部が0.5を超えるならば、case Cへ
case A: result = x SHR b
case B: result = ( ( x + 1 ) * f ) SHR r
ただし、fは切り捨て
case C: result = ( x * f ) SHR r
ただし、fは切り上げ
SHRは論理右シフトのこと
(´・ω・`)Shobomaru 11
12. C言語のプログラム(1)
引数 意味
int short_rcp( div 割る数
unsigned short div, rcp 逆数
unsigned short *rcp,
int *shift, shift 論理右シフト量
unsigned short *bias ) bias 補正
{
int b = 0; 戻り値 divが2の冪乗か否か
for( int i = 0; i < 16; i++ ) {
if( ( ( div >> ( 15 - i ) ) & 0x1 ) == 1 ) {
b = 15 - i;
break;
}
}
unsigned int r = 16 + b;
unsigned int r2 = 1 << r;
double f = (double)r2 / div;
double fm = fmod( f, 1.0 );
(´・ω・`)Shobomaru 12
13. C言語のプログラム(2)
if( fm == 0.0 )
{
*shift = b;
*rcp = 1;
*bias = 0;
return 1;
}
else if( fm < 0.5 )
{
*shift = b;
*rcp = (unsigned short)f;
*bias = 1;
return 0;
}
else
{
*shift = b;
*rcp = (unsigned short)( f + 0.5 );
*bias = 0;
return 0;
}
} (´・ω・`)Shobomaru 13
14. C言語のプログラム(3)
const unsigned short dividend = 10;
const unsigned short divisor = 5;
unsigned short rcp;
int shift;
unsigned short bias;
int ans;
int pow2 = short_rcp( divisor, &rcp, &shift, &bias );
if( pow2 ) ans = dividend >> shift;
else ans = ( ( dividend + bias ) * rcp ) >> ( shift + 16 );
• ansは期待通り”2”
• 割られる数が32769以上のとき、不正な解を出す
– C言語の整数拡張ルールの関係で、乗算が符号付きに
なってしまう
– 楽しいアセンブラプログラミングが待ち受ける
(´・ω・`)Shobomaru 14
15. 逆数求めるの面倒すぎじゃね?
• だから言っただろう、
「ただし、除数が固定なら」と。
– 面倒な計算も初回だけなら我慢できる
• 除数が固定なら、変数pow2も不変なので、
条件分岐のコストは考えなくてよい
– Branch Target Bufferのない糞CPUなんぞ知らん
• 整数拡張もSSEなら自分で操作できる
– アセンブラいらない!
(´・ω・`)Shobomaru 15
16. SSE2を使ったプログラム
__m128i mdivident;
__m128i mrcp = _mm_set1_epi16( rcp );
__m128i mbias = _mm_set1_epi16( bias );
__m128i mans;
mdivident = _mm_load_si128( [メモリアドレス] );
if( pow2 ) mans = _mm_srli_epi16( mdibident, shift );
else mans = _mm_srli_epi16( _mm_mulhi_epu16(
_mm_add_epi16( mdivident, mbias ), mrcp ), shift );
• _mm_mulhi_epi16 ()は乗算後の上位ビットを返す
– 上位型への拡張は要らない
– 【悲報】上位ビットを返す乗算は、符号つきorなしの
16bit整数しかない
• 8bitなら16bitにunpack、32bitは終了
(´・ω・`)Shobomaru 16
17. 18. 実は賢いコンパイラ
• 実は、C言語で定数の除算式を書くと
勝手に乗算+論理右シフトにしてくれる
– 割る数が2の冪乗なら右シフトだけ
volatile unsigned int dividend = 8;
unsigned int ans = dividend / 5;
mov ecx, ***
mov eax, 0CCCCCCDh
mul eax, ecx
shr edx, 2
(Visual C++ 10.0 / Release)
(´・ω・`)Shobomaru 18
19. BSR命令を使った最適化(2)
• 実は、有効ビット数の計算はx86専用命令がある
• BSR命令
– ただし、0(立っているビットがない)は未定義値
• 除算なので、そもそも逆数に0が入ってくる時点でおかしい
– assert()なりthrowなり自分で例外処理する
• 0が未定義でないLZCNT命令もあるが、AMD専用(SSE4a)
– イントリンシック命令
• _BitScanReverse() (Visual C++) ※intrin.hをinclude
• _bit_scan_reverse() (Intel C++ Compiler)
• __builtin_clz() (GNU gcc)
– ARMとかMIPSとかでも使える
– xor 16を取る必要あり?(要確認)
(´・ω・`)Shobomaru 19
20. BSR命令を使った最適化(2)
unsigned long bl;
_BitScanReverse( &bl, div );
//int b = 16;
//for( int i = 0; i < 16; i++ ) {
// if( ( ( div >> ( 15 - i ) ) & 0x1 ) == 1 ) {
// b = 15 - i;
// break;
// }
//}
int b = bl;
• といっても逆数を求める部分なので、
効果はほとんどない
(´・ω・`)Shobomaru 20
21. _mm_set1_epi16()
• 実は複数の命令に変換されてしまう
– mov + punpcklwd + pshufd
• SSSE3なら_mm_shuffle_pi8()、
AVX1なら_mm_broadcastw_epi16()
でpunpcklwdは不要になる
– movは消せないけど、IvyBridgeからmovはリネームス
テージで消滅するらしいから、多分気にしないでいい
• AMD?なにそれおいしいの?
(´・ω・`)Shobomaru 21
22. 23. 24. 25. ARM NEONでは…
• NEONも整数の除算はない
• 乗算はある
– VQDMULH命令
• ただし、符号つき16/32bitのみ…
– VMULL命令
• 符号なし8/16/32bit、後で自分で上位ビットを取り出す
• なぜか整数の逆数命令もある
– VRECPE/VRECPS命令
• 符号なし32bit(と32bit小数)
– 精度とかはよく知らない
• Newton-Raphson法が必要?試すのマンドクセ(‘A`)
(´・ω・`)Shobomaru 25
26. 27. 28.