/
「 AMD 「 AMD

「 AMD - PowerPoint Presentation

olivia-moreira
olivia-moreira . @olivia-moreira
Follow
457 views
Uploaded On 2016-10-13

「 AMD - PPT Presentation

で使うと遅いんだけど x86x64 最適化勉強会 4 LT 梅澤威志 UMEZAWA Takeshi umezawatakeshi Q dis って んの A disasm なら少々 自己紹介 ID: 475126

virtualalloc mem height ditto mem virtualalloc ditto height readwrite reserve commit page width null srcbegin 0x80 srcend 64kib 8bpc

Share:

Link:

Embed:

Download Presentation from below link

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.


Presentation Transcript

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: さあ…

Related Contents


Next Show more