で使うと遅いんだけど x86x64 最適化勉強会 4 LT 梅澤威志 UMEZAWA Takeshi umezawatakeshi Q dis って んの A disasm なら少々 自己紹介 ID: 475126
Download Presentation The PPT/PDF document "「 AMD" is the property of its rightful owner. Permission is granted to download and print the materials on this web site for personal, non-commercial use only, and to display it on your personal computer provided you do not modify the materials and that you retain all copyright notices contained in the materials. By downloading content from our website, you accept the terms of this agreement.
Slide1
「AMDで使うと遅いんだけど」x86/x64最適化勉強会 #4 LT
梅澤威志
(UMEZAWA Takeshi)
@
umezawa_takeshiSlide2
Q: dis ってんの?A: disasm
なら少々
…Slide3
自己紹介映像可逆圧縮コーデックUt Video Codec Suite の作者
※
http
://umezawa.dyndns.info/wordpress/?cat=28
ある2ちゃん
ねら
ー曰く、
UtVideo
唯一の欠点
作者が
ニコ厨
※
http://pc11.2ch.net/test/read.cgi/avi/1205486331/178
まったくツンデレなんだから
…Slide4
前置き今回話すことは、何人かの人は過去の x86/x64最適化勉強会で雑談などで既に聞いているはずです。
blog
を検索しても出てきます。
知ってる
人は寝てていいです。Slide5
あるユーザの報告「AMD で ULRG や
ULRA
を使うとエンコードがすごい遅いんだけど」
ULRG
は内部保持形式が
RGB 8bpc
のもの。
ULRA
は同じく
RGBA 8bpc
のもの。
ULY2
(
YUV422
8bpc)
や
ULY0 (YUV420 8bpc)
は遅くないらしい。
デコード
はエンコードほどではないが、やっぱり遅いことは遅いらしい。Slide6
実測確かに遅い。ULRG は 24bpp であり、
16bpp
である
ULY2
と比較して同じ画像サイズの時
1.5
倍ぐらい遅いことが期待されるが、エンコードの場合は
期待されるより
3
倍ぐらい遅い
。
明らか
に何かおかしいSlide7
エンコーダの実装以下の順序で処理する。Packed → Planar
変換
フレーム内
予測
ハフマン
符号化
フレーム内予測とハフマン符号化
は種類によらず全く同じ処理なので、
Planar
変換に問題がありそう。
本来は全体の
1
割ぐらいの時間なんだけど
…Slide8
Planar 変換r =
VirtualAlloc
(NULL, width * height,
MEM_COMMIT|MEM_RESERVE,
PAGE_READWRITE);
g =
(ditto)
b =
(ditto)
for (p =
srcbegin
; p <
srcend
; p += 3) {
*(g++) = p[1];
*(b++) = p[0] - p[1] + 0x80;
*(r++) = p[2] - p[1] + 0x80;
}Slide9
ちょっと変えてみる…速度変わらずr =
VirtualAlloc
(NULL, width * height,
MEM_COMMIT|MEM_RESERVE,
PAGE_READWRITE);
g =
(ditto)
b =
(ditto)
for (p =
srcbegin
; p <
srcend
; p += 3) {
*(g++) = p[1];
*(b++) = p[0] - p[1];
// + 0x80;
*(r++) = p[2] - p[1];
// + 0x80;
}Slide10
さらに変えてみる…やっぱり遅いr =
VirtualAlloc
(NULL, width * height,
MEM_COMMIT|MEM_RESERVE,
PAGE_READWRITE);
g =
(ditto)
b =
(ditto)
for (p =
srcbegin
; p <
srcend
; p += 3) {
*(g++) = p[1];
*(b++) = p[0];
// - p[1] + 0x80;
*(r++) = p[2];
// - p[1] + 0x80;
}Slide11
遅くなくなった!?r = VirtualAlloc
(NULL, width * height,
MEM_COMMIT|MEM_RESERVE,
PAGE_READWRITE);
g =
(ditto)
b =
(ditto)
for (p =
srcbegin
; p <
srcend
; p += 3) {
*(g++) = p[1];
*(b++) = p[0];
r++;
}Slide12
対照群:遅いままr = VirtualAlloc
(NULL, width * height,
MEM_COMMIT|MEM_RESERVE,
PAGE_READWRITE);
g =
(ditto)
b =
(ditto)
for (p =
srcbegin
; p <
srcend
; p += 3) {
*(g++) = p[1];
*(b++) = p[0];
*(r++) = 0;
}Slide13
ULY2 の場合(遅くない)y
=
VirtualAlloc
(NULL, width * height,
MEM_COMMIT|MEM_RESERVE,
PAGE_READWRITE);
u =
VirtualAlloc
(NULL, width * height / 2,
MEM_COMMIT|MEM_RESERVE,
PAGE_READWRITE);
v =
(ditto)
for (p =
srcbegin
; p <
srcend
; p += 4) {
*(y++) = p[0];
*(u++) = p[1];
*(y++) = p[2];
*(v++) = p[3];
}Slide14
Q: なぜこうなるのでしょう?Slide15
A: store で毎回 L1 キャッシュミス
するからSlide16
VirtualAlloc()呼び出しプロセスのアドレス空間を予約あるいはコミットする。POSIX
の
mmap
()
に似ている。
予約あるいはコミットするアドレスは「割り当て粒度
(allocation
granularity)
」に丸められる。
ページサイズ
(=4KiB)
ではない。
少なく
とも
Windows XP
~
7
において
は
、
Win32
での
割り当て
粒度
は
64KiB
である。Slide17
AMD の L1 キャッシュ長らく 命令 64KiB +
データ
64KiB
の構成
長らく
2-way
セットアソシアティブ
→
32KiB
ごとに同じエントリアドレスになる。Slide18
両方合わせると…VirtualAlloc() で割り当てられたバッファは 64KiB
境界に整列しているので、各バッファの先頭アドレスは全て同じエントリアドレスを持つ。
ULRG
では
g, b, r
のポインタが同じ速度で進み「常に」同じエントリアドレスになるため、
1
バイトアクセスするたびにキャッシュミスして猛烈に遅くなる。Slide19
解決方法ポインタが同じ速度で進むのだから、最初からずらしておけば今度は絶対に同じエントリアドレスにはならない。p は
3
倍速で進むのでエントリアドレスが重なることがあるが、その時でも同じエントリアドレスを使っているのは
2
つだけなので
セーフ。Slide20
これで解決r = VirtualAlloc
(NULL, width * height,
MEM_COMMIT|MEM_RESERVE,
PAGE_READWRITE);
g =
VirtualAlloc
(NULL, width *
height
+ 256
,
MEM_COMMIT|MEM_RESERVE,
PAGE_READWRITE
)
+ 256
;
b =
VirtualAlloc
(NULL, width *
height
+ 512
,
MEM_COMMIT|MEM_RESERVE,
PAGE_READWRITE
)
+ 512
;
…
※
256
でいいかどうかは議論(というか計測)の余地がある。Slide21
当時(あまり)考えなかったことL1 キャッシュを共有する複数の物理スレッドIntel HT とかのことだが、
Intel
系だと
8-way
なので、
2
スレッド走っても
1
スレッドあたり
4-way
で問題なし。
AMD Bulldozer
の場合、
L1
は
Bulldozer
モジュールごとではなくコアごとに持ってるらしいから、半分にはならない?Slide22
まとめ?キャッシュの連想度にも(たまには)気を付けましょう。でも 2-way はひどいと思います。
Intel
は
8-way
なのに。Slide23
Q: 結局 x86 関係あんの?A: さあ…
?