Nanashi-softプログラマ専用Windows gcc SDL


◇PS3 Linux SDLでプログラミング -DMA転送の効率化-

SPEで処理を行う為には、メインメモリからデータを DMA転送する必要があります
どのように転送を行えば効率が良いのか? を検証より導き出したいと思います

◎検証項目(案)

・16バイト単位で、様々なサイズを転送してみる
・アラインメントを変えてみる
・ギャザーを使ってみる
・複数のSPEを使ってみる

◎PPE側プログラム

SPEの検証なので、PPE側のプログラムはほぼ固定にします
PPE側プログラムは別ページにて

内容は 1920×1080×4byteのデータを SPEから取得すると言うものです
画面データを高速転送したい、というイメージです

◎16バイト単位で、様々なサイズを転送してみる

SPE側から 16バイト単位、32バイト単位、48バイト単位……と、16バイトずつ増やしてデータを取得してみます
SPE側プログラムは別ページにて

処理単位(byte) 処理時間(ミリ秒)

16

8053

32

4100

48

3323

64

2566

80

2029

96

1745

112

1476

128

1323

144

1168

160

1081

176

1011

192

944

処理単位を増やす事で速度が上がっていきました
これより、DMA転送命令を出すのにコストがかかる事がわかりました
命令回数は1回でも少ない方が良いと言うわけです

更に処理単位を上げて計測を続けると、大きな問題が発生しました
処理単位(byte) 処理時間(ミリ秒)

560

406

576

405

592

569

608

1293

624

1101

640

1364

656

1431

672

2018

688

2928

704

2651

720

757

736

1920

752

925

768

1428

784

483

800

465

816

343

前後の処理時間よりも明らかに遅くなる時がありました
なぜこうなるのかはわかりませんが、608〜768バイトずつ転送するのはやめた方が良いでしょう

一度に転送するサイズを増やすと速くなるので、どんどんサイズを上げていきました
処理単位(byte) 処理時間(ミリ秒)

16352

176

16368

170

16384

177

16400

Bus Error

16416

Bus Error

16432

Bus Error
16384バイトを超えるとバスエラーになりました
一度に転送できるサイズは16KBまでのようです(実はリファレンスにそう書いてありました(^^;)

◎128バイト単位で、様々なサイズを転送してみる

DMA転送は128バイトアラインメントが効率が良いと言われています
本当にそうなのか? を検証します

○PPE側プログラム変更点
//処理データ
unsigned char data1[1920*1080*4] __attribute__((aligned(16)));

unsigned char data1[1920*1080*4] __attribute__((aligned(128)));

○SPE側プログラム変更点
//データ受け取り用(このサイズを色々変えて計測する)
unsigned char data1[16] __attribute__((aligned(16)));

unsigned char data1[16] __attribute__((aligned(128)));

処理単位(byte) 処理時間(ミリ秒)

464

454

480

438

496

433

512

3622

528

440

544

458

560

415

576

3558

592

527

608

971

624

1090

640

307

656

1343

672

678

688

1220

704

322

720

830

736

363

752

546

768

274

784

952

800

398

816

318

832

287

16バイト境界の時よりもより広範囲に異常がある場所が現れました
512〜784バイトずつ転送するのはやめたほうが良さそうです

16バイトと128バイトでの処理速度を比較してみました
 

128バイト

16バイト

処理単位(byte) 処理時間(ミリ秒)

9600

131

180

9616

174

174

9632

170

180

9648

175

175

9664

157

181

9680

174

174

9696

169

181

9712

174

175

9728

131

180

9744

174

174

9760

171

180

9776

174

175

9792

156

181

9808

174

175

9824

169

181

9840

175

174

9856

131

179

ほとんど処理速度に違いはありませんが、128バイト境界時に128バイトで割り切れる値で処理を行った時には顕著に速くなりました
逆に言うと、128バイト倍数で転送を行わないのであれば、大きくアラインメントを取る分メモリ効率が落ちるだけ損と言うことになります

◎現状のまとめ

○DMA転送効率化の条件
1)データはできる限りまとめて転送する
2)608〜708バイトずつ転送するのは避ける
  128バイトアラインメントの時は512〜784バイトずつ転送するのは避ける
3)1度に転送できるのは16384バイト(16KB)まで
4)128バイトアラインメントで変数を宣言し、128バイトの倍数で転送を行う

尚、環境は
・Fedora Core 5
・Linux Kernel 2.6.16(PS3アドオンCDデフォルト)
・Cell SDK 2.0
です

《補足》
以下の環境にて同様の検証を行った場合、2)の異常転送は発生しませんでした
・Fedora Core 6
・Linux Kernel 2.6.21(PS3アドオンCDに同梱されているもの)
・Cell SDK 2.1


TOPプログラマ専用PS3 Linux SDL