アセンブラに関するマジ質問だけど
■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん
NGNGどうにも速度が出ないんだよね・・・・
下に俺のソースの抜粋書くから、
わかる人は教えてくれないかな・・・?
0002デフォルトの名無しさん
NGNG64KB境界に合わせておいて、
mov EBX, [Table]
というふうにEBXに入れておく。
で、下が<半透明書き込み部分>
mov BL, [ESI] //転送元をBLに
mov BH, [EDI] //転送先のBHに
mov AL, [EBX] //書き込む色をALに
mov [EDI],AL
inc EDI
あとは横×縦のループでこれを囲む。
0003デフォルトの名無しさん
NGNG0004デフォルトの名無しさん
NGNG1,1,5,2、1。
mov AL, [EBX] でストールが発生しちゃってるんだよね・・・
かといって、普通にADD使うと遅そうだし。
0005デフォルトの名無しさん
NGNG上のほう見てなかったんで。
もしわかる人いたらsageでいいから頼む・・・
0006デフォルトの名無しさん
NGNGデータを3個くらい並列処理したら?
0007デフォルトの名無しさん
NGNGこれってもろパーシャルレジスタストールじゃない?
P6系ではBLとBHを別々に書き込んで、EBXで合わせて使うと
ストールが発生したはず。
そのまま素直にシフト+加算で計算した方がいいよ。
00087
NGNG0009デフォルトの名無しさん
NGNG下位だけ書き換えちゃいけなかったのね。
0010デフォルトの名無しさん
NGNG>>7
どうもありがとう。
並列は、ループでECX,EDX使ってるから
ちょっと無理そう。(EDI,ESIは各矩形のポインタ)
ADD+シフトでやってみるよ。
0011デフォルトの名無しさん
NGNG普通にシフトと足し算でやるにしても
結局下位8にロードして、左8シフト。さらに下位8にロードして
ポインタを足すわけでしょう?
結局このストールがおきるんじゃないのかな?
0012デフォルトの名無しさん
NGNGmov EBX, [ESI]
mov EAX, [EDI]
and EBX, 255
and EAX, 255
shl EAX, 8
add EBX, tbl
add EBX, EAX
mov AL, [EBX]
mov [EDI],AL
inc EDI
inc ESI
inc EDX
というふうに修正したら、
9クロックから6クロックまであがったよ。
まだまだ実用的じゃないみたいだけど大きな進歩だね。
本当にありがとう。
0013デフォルトの名無しさん
NGNGこれが6。
mov EBX, [ESI]
mov EAX, [EDI]
and EBX, 255
and EAX, 255
shl EAX, 8
add EBX, cll
add EBX, EAX
inc EDI
inc ESI
inc EDX
mov AL, [EBX]
mov [EDI-1],AL
0014デフォルトの名無しさん
NGNGパーシャルレジスタストールはP6のアウトオブオーダー実行コアの
命令スケジューラの制限じゃないかな?
パーシャルレジスタアクセスを行うとP6の命令スケジューラがマヒするんだと思う。
Pentium4ではパーシャルレジスタストールは無いらしい。
0015デフォルトの名無しさん
NGNGmov EBX, [ESI]
mov EAX, [EDI]
and EBX, 255
and EAX, 255
は
movzx EBX, byte ptr [ESI]
movzx EAX, byte ptr [EDI]
でいいんじゃないかな。
0016デフォルトの名無しさん
NGNG>>14
なるほどね・・・・
てことは、Pentium4では、最初のが最速になるってことか。
本当に高速化を目指すならCPUごとに条件分岐すれば一番なのか・・・
>>15
おっと、盲点・・・・・恥ずかしい所を見せたか(^^;
0017デフォルトの名無しさん
NGNGというか、もうこれ以上はできない気がする。
できて4だろうが、それでも実用には向かない。
なぜだろう?
暇な人がいたら、でいいんだが
以下に半透明部分の全ソースを書くので
問題点があったら教えてくれないかな?
ずうずうしいとは思うんだが、もしできたら頼みたい・・・
_asm{
mov EDI, dat1 //EDIに転送元のポインタ(左上の点)
mov ESI, dat2 //ESIに転送先のポインタ(左上の点)
add EDI, Dot1 //EDIを転送開始点までずらす(X+Y*WIDTHを足す)
add ESI, Dot2 //ESIを転送開始点までずらす(X+Y*WIDTHを足す)
mov EBX, tbl //加算テーブル開始ポインタ
// 外側ループ開始
mov ECX, 0 // ループカウンタ(Y)
FOR_START_Y:
push EDI //EDI退避
push ESI //ESI退避
// 内側ループ開始
mov EDX, 0 // ループカウンタ(X)
FOR_START_X:
movzx EBX, byte ptr [ESI]
movzx EAX, byte ptr [EDI]
shl EAX, 8
add EBX, tbl
add EBX, EAX
inc EDI
inc ESI
inc EDX //Xカウンタのインクリメント
mov AL, [EBX]
mov [EDI-1],AL
cmp EDX, Width //横幅
jl FOR_START_X
// 内側ループ終了
pop ESI //ESI復旧
pop EDI //EDI復旧
add EDI, W1
add ESI, W2
inc ECX //Yカウンタのインクリメント
cmp ECX, Height //縦幅
jl FOR_START_Y
// 外側ループ終了
}
0018デフォルトの名無しさん
NGNGxor ebx, ebx
mov bl, byte ptr [ESI]
xor eax, eax
mov ah, byte ptr [EDI]
inc EDI
lea ebx, [cll + eax + ebx]
inc ESI
mov AL, [EBX]
inc EDX
mov [EDI-1],AL
で 5。
0019デフォルトの名無しさん
NGNGbyte 単位でメモリアクセスしているのを dword 単位のアクセスにできるだろう。
0020デフォルトの名無しさん
NGNGDirectXならハードウェアで半透明やってくれるじゃん。
0021デフォルトの名無しさん
NGNG何で計測しているのですか?
0022>16
NGNG0023デフォルトの名無しさん
NGNG煽りにしてもベタでつまらんな。
0024sage
NGNGpush ESI //ESI退避
pop ESI //ESI復旧
pop EDI //EDI復旧
上のペアになる命令は要らないんじゃん?
W1とW2からあらかじめWidthを引いておけば。
mov EDX, 0 // ループカウンタ(X)
cmp EDX, Width //横幅
これとかも
mov EDX, Width
test EDX, EDX
としたほうが大抵速い。
せめて
xor EDX, EDX // ループカウンタ(X)
cmp EDX, Width //横幅
としよう。
x86で、レジスタを0クリアするのに0を代入するか、普通?
mov [EDI-1],AL
これもあんまり良くないかも。
キャッシュを管理しているOSだと、
ライトキャッシュ効かなくなって遅くなることあるよ。
0025sage
NGNG当然気づいたとは思うけど、
mov EDX, 0 // ループカウンタ(X)
inc EDX //Xカウンタのインクリメント
cmp EDX, Width //横幅
を
mov EDX, Width // ループカウンタ(X)
dec EDX //Xカウンタのインクリメント
^^^
test EDX, EDX
としてね。
ついでに言えば、testいらねーや。
mov AL, [EBX]
mov [EDI],AL
dec EDX //Xカウンタのインクリメント
jnz FOR_START_X
として。
つーかIAマニュアル読め。
0026デフォルトの名無しさん
NGNG>>18
なるほど。勉強になる・・・・
まともにうごかないのはcllがポインタだからかな?
>>19
ループの展開?
4ドット同時に処理せよということかな?
>>20
DIRECT3Dならね・・・
>>21
ネットで見つけた、誰かのプログラムなんだけど
どうも不安定っぽい。
>>22
そうだね(^^;
0027デフォルトの名無しさん
NGNG>>25
有力な情報ありがとう。
やはり自分はまだまだ未熟だな・・・
やっぱり問題はループにあったのか。
cp+jlって意外と遅かったのね。
とりあえず、現時点のことを全部やったらFPSが52まで出るようになったよ。
みんなありがとう。
0028名無しだよもん
NGNGJECXZを使えばもっとはやいんじゃないの?
0029名無しだよもん
NGNG0030デフォルトの名無しさん
NGNG今のところ、これが最高速?
もうこれ以上はあがらないのかな?
mov EDI, dat1
mov ESI, dat2
add EDI, Dot1
add ESI, Dot2
mov EBX, tbl
// 外側ループ
mov ECX, Height // ループカウンタ(y)
FOR_START_Y:
// 内側ループ
mov EDX, Width // ループカウンタ(x)
FOR_START_X:
//**処理**
movzx EBX, byte ptr [ESI]
movzx EAX, byte ptr [EDI]
shl EAX, 8
add EBX, tbl
add EBX, EAX
inc ESI
mov AL, [EBX]
mov [EDI],AL
inc EDI
dec EDX // Xカウンタのデクリメント
jnz FOR_START_X
// 内側ループ終了
add EDI, W1
add ESI, W2
dec ECX // Yカウンタのデクリメント
test ECX,ECX
jnz FOR_START_Y
// 外側ループ終了
0031デフォルトの名無しさん
NGNGLOOPは複雑命令だから遅い。
0032デフォルトの名無しさん
NGNG0033shige
NGNG0034デフォルトの名無しさん
NGNGってことに気付け。
0035デフォルトの名無しさん
NGNGてか、これでもう最適なのか?
順番変えれば、ペアリングとかできそうじゃない?
0036デフォルトの名無しさん
NGNGネタにネタレスしてやるっ!!!!
>>33
Perlででもアルファブレンディングのルーチン書いて
死んでやがれヴォケ
0037デフォルトの名無しさん
NGNGまあ普通は無駄だけど、MMXとかSIMD使う分には価値があるよ。
0039デフォルトの名無しさん
NGNG0040デフォルトの名無しさん
NGNG最適ではない。
0042デフォルトの名無しさん
NGNGあんまり大きくない奴で。
0043デフォルトの名無しさん
NGNG0044#6411
NGNG出力先はフレームバッファだったりしないかな?
だとすると、抜本的な高速化は別の方法があると思われ。
ここ2年DirectX触れてないから、用語忘れた。…鬱だ…
00451
NGNG本当?
今回は、LOCKを避けるために配列変数から配列変数への転送だけど
それについてはちょっと興味あるな。
なんせ、LOCK使うと遅くなるからサーフェスはほとんどつかわないつもりだったんで。
0047いつでもどこでも名無しさん
NGNG何で1バイトづつやってるの?
0049デフォルトの名無しさん
NGNG最適化前だから。
0050デフォルトの名無しさん
NGNG00511
NGNG>>49
レジスタももう埋まってて使えないし
どうやって並行処理するの?
MMX使うとかしかないのかな?
>>50
unsigned char* test;
unsigned char dummy[256*256*2];
test = (unsigned char *) (((unsigned)dummy + 65535) & (-65536))
っていう方法で。もしかしてちと強引なのかな?
00521
NGNGttp://www.yo.rim.or.jp/~sawara/opt/jk9905.html
WatcomC用ってなってたから、VC++にちょっと改造したけど。
0054デフォルトの名無しさん
NGNGP6以降は、μOP命令に変換されて、空いているスロットを使ってOOO実行とか
しちゃうから、クロックの計算は出来ないでしょう。
#V-Tuneでも、クロックは出ないはず。
>>28
Loopは、今や遅い命令です。
dec ecx
jnz @@@
の方が速いです(ただしP6の話。AMDでは使った方が速い)
また、P6はフラグストールとかって面倒なもんがあるんで、
cmpして判定しないと逆に遅くなったりします。
>>30
あとは、Loop Unrollして、Incとかはなるべく[esi + 01]とかに置き換えた方が良いよ。
0055デフォルトの名無しさん
NGNG最適化好きな人にはここがおすすめだよ。
ttp://homepage1.nifty.com/herumi/adv/adv40.html
00561
NGNGなるほどね。だからクロック数が不安定だったのね。
数値が実行ごとにずれたりしてたから。
Loop Unrollって?
あと、Incなしで [esi + xx]のほうが速いんだ。
上にそっちだと遅いって人がいたけど、マシンによるのかな?
>>53
>>55
情報サンクス。
今から印刷してじっくりと見てみるよ。
0057デフォルトの名無しさん
NGNGleaはフラグが変わらんから分岐の直前でもいいぞ
0058デフォルトの名無しさん
NGNGそうだね。
それより
>>30
で気になるのが、movzxって遅くなかったっけ?
xor eax, eax
mov eax, byte ptr[edi]
としてペアリングした方が大抵速くなかったっけ?
0059デフォルトの名無しさん
NGNGどうでもいいつっこみだけど
xor eax, eax
mov al, byte ptr[edi] ね。
おそいっていうかmovzxやmovsxはペアリングができないんだよ。
xorとmovに分解すればペアリングできる機会が増えるってことで。
いつ出るかなーと思っていたがなかなか出ないので
リンクage
http://www.csl.sony.co.jp/person/fnami/pentopt.htm
http://www.csl.sony.co.jp/person/fnami/asm.htm
0060デフォルトの名無しさん
NGNG多くの場合、lea 命令、またはlea、add、sub、およびshift 命令のシーケンスを定数乗算命令
に代えて使用することができる。Pentium II およびPentium III プロセッサ用に設計されたコードを
最適化するには、整数乗算命令を使用する。lea 命令は、3 つまたは4 つのオペランドを取る加算
命令として使用できることがある。次に例を示す。
lea ecx, [eax+ebx+4+a]
このようにlea 命令を使用することで、複数の算術命令のオペランドでレジスタが占有されること
を避け、レジスタが不要に使われるのを防ぐことができる。
Pentium II およびPentium III プロセッサでは、lea 命令とshift 命令は、どちらも1 サイクルで実
行される単一µop 命令である。しかし、このレイテンシの短さは、将来の使用上でも保たれるかど
うかはわからない。
最適なブレンデッド・コードを得るためには、shift 命令を2 つ以上のadd 命令に置き換えると
よい。これは、この命令のレイテンシがすべての実装面で短いとは限らないからである。
・複雑な命令
一般に4 つよりも多くのµop を持ち、デコードに複数のサイクルが必要な複雑な命令( たとえば
enter、leave、loop) の使用を避ける。代わりに、単純な命令のシーケンスを使用すること。
・8/16 ビットのオペランド
Pentium II およびPentium III プロセッサでは、同じレジスタの排他的論理和をとり、レジスタの
リアがそのレジスタの以前の値に依存しないことを認識する機能を備えている。さらに、上記
コード・シーケンスでのパーシャル・ストールを回避する機能も備えている。詳細については
「パーシャル・レジスタ・ストール」の節を参照のこと。
Pentium II およびPentium III プロセッサでは、パーシャル・ストールの発生を抑えるために、movzx
命令のパフォーマンス向上が図られている。これらのプロセッサ向けのコーディングでは、movzx
命令を使用するとよい。
0061デフォルトの名無しさん
NGNGなんでP5系のペアリングの話が出てくるんだ?
今時P5最適化なんてナンセンスじゃない?
Loop Unrollして、Incを使わず [esi + 1]で処理するというのは
依存性チェーンを断ち切って、P6のOOO実行性能を高めるっていう話でしょ?
0062デフォルトの名無しさん
NGNGhttp://www.intel.co.jp/jp/developer/design/pentiumIII/manuals/index.htm
これを読めばほとんど全部書いてある。ここで人に聞くより、
まずはこれを全部読むことから始めた方が近道だよ。
0063デフォルトの名無しさん
NGNGあ、そうだったのか
> なんでP5系のペアリングの話が出てくるんだ?
>今時P5最適化なんてナンセンスじゃない?
たしかにな(笑)
0064デフォルトの名無しさん
NGNGP6にした方が良いと思うよ。
movzx, movsxは、P6では1μOP。がんがん使いましょう。
あと、最適化マニュアル読めばわかるけど、命令のデコーダが
1Clockで3つの命令をデコードできるんだけど、最初のデコーダのみが
4μOPまでの命令をデコードできて、残りの2つのデコーダは1μOPまで
(要するに超単純な命令)しかでコードできないから、なるべく
μOP命令数で、4-1-1になるように命令を配置した方がいいよ。
なるべくRSを一杯にしといた方が有利だからね > P6
0065デフォルトの名無しさん
NGNGシフトのレイテンシは大きいぞ
油断大敵!
0066デフォルトの名無しさん
NGNG0067デフォルトの名無しさん
NGNG0068デフォルトの名無しさん
NGNG>>62のアーキテクチャ最適化リファレンス・マニュアル読んだか?
0069デフォルトの名無しさん
NGNG00701
NGNGようやくアンロールが理解できたよ。
いくつくらいに展開すりゃいいんだろ。
8?
>>64
あー、だから3つの命令でも例のプログラムで1クロックって出たり
したのか・・・・・納得。バグだと思ってたよ。
4−1−1ね。やってみる。ペアリングとかはもう気にする時代じゃないんだね。
0071デフォルトの名無しさん
NGNG2のコードだけど、マニュアルを読む限り、
xor EBX,EBX
mov EDX, [Table]
:
:
mov BL, [ESI]
mov BH, [EDI]
mov AL, [EDX+EBX]
mov [EDI],AL
inc EDI
にすれば、パーシャルレジスタストールしないで、
ループ出来そうなんだけど、どうなの?
0072デフォルトの名無しさん
NGNGmov BH, [EDI]
の行がなければストールしない。
この行があるからストールする。
0073デフォルトの名無しさん
NGNGEBPは?
0074デフォルトの名無しさん
NGNGmov EAX, [EDI]
movzx EBX, byte ptr [ESI]
add EBX, tbl
XLATB
ror EAX,8
movzx EBX, byte ptr [ESI+1]
add EBX, tbl
XLATB
ror EAX,8
movzx EBX, byte ptr [ESI+2]
add EBX, tbl
XLATB
ror EAX,8
movzx EBX, byte ptr [ESI+3]
add EBX, tbl
XLATB
ror EAX,8
LEA ESI,[ESI+4]
LEA EDI,[EDI+4]
mov [EDI],EAX
0075デフォルトの名無しさん
NGNG0076デフォルトの名無しさん
NGNGそれから ECX,,EDXをループカウンタに使うのは勿体ないよ
ECXは無条件にスタック上で処理すればいいし
EDXも内側の処理が短くできるならスタック上に取った方がいいよ
XLATBは パーシャルレジスタストールの対象になると思うから
この2つのレジスタを参戦させて
mov EAX, [EDI]
mov EBX, [ESI]
ror EBX,8
MOV EDX,EAX
SHLD EDX,EBX,8
AND EDX,0xffff
ADD EDX,tbl
movzx ECX, byte ptr [EDX]
SHRD EAX,ECX,8
ror EBX,8
MOV EDX,EAX
SHLD EDX,EBX,8
AND EDX,0xffff
ADD EDX,tbl
・・・繰り返し・・
007776
NGNG早くなる可能性がありそうな気がする 固定じゃないんだったらEBPを使ったらどう?
007876
NGNG0079デフォルトの名無しさん
NGNGFOR_START_X:
movzx EDX, byte ptr [ESI]
movzx EBX, byte ptr [ESI+1]
movzx ECX, byte ptr [EDI]
movzx EAX, byte ptr [EDI+1]
shl EAX, 8
shl ECX, 8
add EBX, tbl
add EDX, tbl
LEA ESI,[ESI+2]
add EBX, EAX
add EDX, ECX
mov AL, [EBX]
mov AH, [EDX]
mov [EDI ],AL
mov [EDI+1],AH
dec [ESP]; //スタックをカウンタに
LEA EDI,[EDI+2]
jnz FOR_START_X
pop EAX;//読み捨て
0080デフォルトの名無しさん
NGNG008164
NGNG0082デフォルトの名無しさん
NGNG00831
NGNG最初、上のソースが何やってるかさっぱりだったよ。
とりあえず1行ずつ追っていって、なんとかどういう意味なのかわかったよ。
>>74
4つ平行か。
EAXをいちいち読むよりこっちのほうが早いんだ?
>>76
これはどうやってループにするの?
79のソースみたいにスタックを使えばいいのかな?
ためしにやってみたけど、なんか遅かった・・・おかしいな?
>>79
スタックを使ったカウンタのやり方サンクス〜
0084デフォルトの名無しさん
NGNGttp://www.keiyu.com/doc/pdftxt.htm
ttp://www.geocities.com/taketakohei/pdf2txt.html
英語なら
ttp://www.ra.informatik.uni-stuttgart.de/%7Egosho/pdftohtml/index.html
008579
NGNGする可能性有り
>>76のコードは 4つ一度にロードしてるけど、
EDXを連続して操作してるから思ったより
早くないかもしれないね。
あ、でも>>79は push Width/2 に変えてね
008664
NGNGmov ebx, table
mov esi, src_pixel
mov edi, dst_pixel
lopY:
mov ecx, nWidth
shr ecx, 2 // 4回Unroll
mov nDivided_Counter, ecx // Unroll用のループ回数
cmp ecx, 0 // P6ではフラグストールするのでcmpする
jz short modulo // 余った分の処理
lopX:
movzx eax, byte ptr [esi + 00] // 1 : src0 load
movzx edx, byte ptr [edi + 00] // 1 : dst0 load
shl eax, 8 // 1 : scaling(*256)
lea edx, [ebx + edx] // 1 : table + index
mov ecx, byte ptr [esi + 01] // 1 : src1 load
mov al, byte ptr [edx + eax] // 1 : table load
mov byte ptr [edi + 00], al // 2 : store0
shl ecx, 8 // 1 : scaling
movzx eax, byte ptr [edi + 01] // 1 : dst1 load
lea edx, [ebx + ecx] // 1 : table + scaler
mov ecx, byte ptr [esi + 02] // 1 : src2 load
mov al, byte ptr [edx + eax] // 1 : table load
mov byte ptr [edi + 01], al // 2 : store1
shl ecx, 8 // 1 : scaling
movzx eax, byte ptr [edi + 02] // 1 : dst2 load
lea edx, [ebx + ecx] // 1 : table + scaler
mov ecx, byte ptr [esi + 03] // 1 : src3 load
mov al, byte ptr [edx + eax] // 1 : table load
mov byte ptr [edi + 02], al // 2 : store2
shl ecx, 8 // 1 : scaling
movzx eax, byte ptr [edi + 03] // 1 : dst2 load
lea edx, [ebx + ecx] // 1 : table + scaler
add esi, 4 // 1 :
mov al, byte ptr [edx + eax] // 1 : table load
mov byte ptr [edi + 03], al // 2 : store3
add edi, 4 // 1
dec nDivided_Width // 2 : LoopCounter
jnz short lopX // 1
008764
NGNGmodulo:
mov ecx, nWidth // 横幅取得
and ecx, 3 // Unroll余り分
// Unrollで余った分だけやる
modulo_lopX:
movzx eax, byte ptr [esi]
movzx edx, byte ptr [edi]
shl eax, 8
lea edx, [ebx + edx]
add edx, eax
mov al, byte ptr [edx]
mov byte ptr [edi], al
inc esi
inc edi
dec ecx
jnz short modulo_lopX
// Y方向のポインタ計算はここでやって!
// テーブルの内容が連続しているならこれで良い
dec nHeight // ちょっと手抜き
jnz short lopY
008864
NGNGコメント以下の数字:が、P6のμOP数です。
もっと詰められるけど、まぁこんな感じでUnrollして
4-1-1配置にすれば良いという参考までに。
あとは、ループの先頭を16Bytesにアラインする、
テーブルをキャッシュにプリロードする、
SSE使っていいなら、prefetch命令を最内周ループの
先頭に入れて、次のループ分をキャッシュに入れちゃうとか
まぁそんなところで。
0089デフォルトの名無しさん
NGNGそうね。一見速そうに見える>>76のコードは実は遅い。
なぜかというと、上から下まで同一レジスタが生きているので処理順序を強制され、
アウトオブオーダー&レジスタリネームがほとんど生きない。
この半透明アルゴリズムでボトルネックはどこかというと、この
movzx ECX, byte ptr [EDX]
64KBのテーブルを読む部分。
64KBのテーブルをランダムにアクセスするので、1次キャッシュをミスする可能性が高く、
ここで処理が滞る事が多い。
だから、ここで処理が滞っても、アウトオブオーダーで次のドットを先に処理できるように、
コードを工夫した方がいい。
0090デフォルトの名無しさん
NGNG今後はますます平行処理出来る事をCPUにどう知らせるかが高速化の
決め手になるんだからさ
0091デフォルトの名無しさん
NGNG0092デフォルトの名無しさん
NGNG>SSE使っていいなら、prefetch命令を最内周ループの
>先頭に入れて、次のループ分をキャッシュに入れちゃうとか
とりあえず、ダミーで最内周ループ先頭に
mov al,[esi+4]
mov al,[edi+4]
って入れちゃえばいいんじゃない?
実際に入れてみるとちょっと速くなるみたい。
0093デフォルトの名無しさん
NGNGESPもあるぞ
0095デフォルトの名無しさん
NGNG100Mのマシンでも1秒50フレームは処理出来るじゃないか
いったいなぜ不満が?
009679
NGNG昔は読み書き回数 減らせばそれだけ早くなった
んだけどなあ・・・というか最近最適化なんてやってないな
0097#6411
NGNGターゲットがMMXなP55Cだったけど、いかに1次キャッシュの上で
処理を完結させるかがキモだったような気もしたり。
バリバリ半透明合成やっても、20fpsくらいは出てたぞ〜
VTuneのトライアル版にだいぶお世話になったがの。
0098デフォルトの名無しさん
NGNGP6の場合、整数演算実行ポートとロード・ストア実行ポートが別々になっているので、
1次キャッシュにヒットするロード・ストアは有効に使った方がいい場合がある。
無理にレジスタのみで処理しようとすると、整数演算実行ポートばかりが飽和してしまい、
ロード・ストア実行ポートはガラ空きという、もったいない状況になる場合がある。
0099デフォルトの名無しさん
NGNGま、用途にもよるか。
# demoならOK。ADVゲームならOK。アクションなら×ってか。
0101デフォルトの名無しさん
NGNG0102デフォルトの名無しさん
NGNGMMXはテーブルにアクセスできないからね。
このアルゴリズムではMMXは使えない。
テーブルが簡単なものであれば、テーブルを使うのをやめて地道に計算→MMX化はできるけど、
テーブルが複雑なものであれば無理。
0103デフォルトの名無しさん
NGNG0104デフォルトの名無しさん
NGNGLH R0,0(,R1)
LTR R0,R0
BZ ABEND
BCTR R0,0
STC *+5
MVC PARMSTR(0),2(R1)
これを知っている人は"化石決定"です。
0105デフォルトの名無しさん
NGNG0106デフォルトの名無しさん
NGNGこれ以上はないでしょう。
0107#6411
NGNG重いセル合成などやらない方針にしてたと思う。
ちなみに出力先サーフェスは16bit(ビット配置はさまざま)だった。
0108デフォルトの名無しさん
NGNG640x480x16で20fpsも出てくれません。
全画面ブレンドして60fpsは無理でしょうか?
ブレンドも50%固定でなく、0〜100%でやってます。
CPUは400MHzです。
0109#6411
NGNGhttp://www.intel.co.jp/jp/developer/design/pentium/manuals/
アルファブレンドとかパッキングに関しては、下記から登録して、
Imageとかそのあたりを読み漁ってもらえれば。ただしぜんぶ英語。
http://developer.intel.com/software/idap/
漏れの経験では、P55C-266にて、640x480x16の
全画面クロスフェードが25fps超えてた。(DX5の時代)
当時のKlamath-266では、40fpsくらい逝ってた記憶も。
どうしても速くならなかったら、ソースの一部示せ。
なお、DirectDrawオンリーでなければ、最近のマシンでは60fps楽勝だ。
0110#6411
NGNGちなみに、当時のK6-2でもまともな速さで動いてたけど、
MMX器が1つしかないK6とかCyrix 686MXでは、トホホな感じだった。
VTuneでPentium最適化にしてしまったからのー。
0111デフォルトの名無しさん
NGNGやってる事が分かりやすいように、命令の順番を変えてませんし、
本当に早いか測ってませんが、ループの中身が、こんなのはどうですか?
P6のコストが、いまいち良く分からんので、自信はないけど、
P6に合わせて最適化すれば86のループよりは早くなりそうかと…。
(EBPはテーブル)
lopX:
mov eax, dwrod ptr [esi+000h]
mov ebx, dwrod ptr [edi+000h]
rol eax, 8
mov ecx, eax
mov edx, ebx
and eax, 000ff00ffh
and ebx, 0ff00ff00h
and ecx, 0ff00ff00h
and edx, 000ff00ffh
or ebx, eax
or ecx, edx
rol ebx, 8
movzx eax, cx
movzx edx, bx
shr ebx, 16
shr ecx, 16
mov al, byte ptr[ebp+eax]
mov bl, byte ptr[ebp+ebx]
mov cl, byte ptr[ebp+ecx]
mov dl, byte ptr[ebp+edx]
mov byte ptr[edi+000h], al
mov byte ptr[edi+001h], bl
mov byte ptr[edi+002h], cl
mov byte ptr[edi+003h], dl
add esi, 4
add edi, 4
dec nDivided_Width
jnz short lopX
0112デフォルトの名無しさん
NGNGうーん、ちょっと見た限りでは>>86-87もいいけど
>>79 も同じくらいの速さは出るようにに思うんだがなあ
特にAthlonだと 79の勝ちのように思う
0113112
NGNGさらに微妙な所を狙うなら後半のループの部分で
add はフラグが変化するから
LEA esi,[ esi+4]
mov al, byte ptr[ebp+eax]
mov bl, byte ptr[ebp+ebx]
mov cl, byte ptr[ebp+ecx]
mov dl, byte ptr[ebp+edx]
dec nDivided_Width
mov byte ptr[edi+000h], al
mov byte ptr[edi+001h], bl
mov byte ptr[edi+002h], cl
mov byte ptr[edi+003h], dl
LEA edi,[ edi+4]
jnz short lopX
と速めにJNZが使うフラグを確定させてやった方がいいかも
0115112
NGNGこの場合間に入れた演算命令がLEAだけだから
>依存関係を解消するために必要以上に離れていると
>前の命令の結果は現在の命令側のμop が必要とし
>た時点で、もはやディスパッチ・バッファに残っていない
>可能性がある。
だけど
>基本的な目安は、依存関係が解消されるだけの時間を
>取りながらも、バッファから結果データが失われるほど長
>時間ではない程度
だから、 LEA1個くらいなら大丈夫なんでは?
0117デフォルトの名無しさん
NGNGAthlonだとそんなに>>111が速い?
うちのPentiumIIだと>>111より>>86の方が若干速いみたいよ。
0118112
NGNGAthlonは整数演算もアドレス演算もパイプラインが3つあるから途中の
同種命令が固まってあっても苦にならないんだろうね
PenII/IIIは整数演算ユニットは2つで、シフトは片方でしか実行出来ない
から、 それ用に命令の順番を変更してみたらどうよ?
0119デフォルトの名無しさん
NGNG0120デフォルトの名無しさん
NGNGAthlonだと1ピクセル当たり何クロックで処理できるの?
0121デフォルトの名無しさん
NGNG2個ってことは、ペアリングとか?
0122111
NGNG後半部分が、上手く動かない可能性が高いので、
論理和、シフト、ゼロ拡張付きロード、「add esi, 4」、
「sub nDivided_Width, 001h」の位置を適当に入れ替えてみたり、
前回のように、1バイトずつストアする方法に戻してみたりして下さい。
(今回もEBPはテーブル)
lopX:
mov edx, dwrod ptr [esi+000h]
mov ecx, 000ff00ffh
mov ebx, 0ff00ff00h
mov eax, dwrod ptr [edi+000h]
and ecx, edx
and edx, ebx
and ebx, eax
shl ecx, 8
and eax, 000ff00ffh
shr ebx, 8
or ecx, eax
or edx, ebx
movzx eax, cx
shr ecx, 16
add edi, 4
movzx ecx, byte ptr[ebp+ecx]
movzx ebx, dx
shr edx, 16
movzx ebx, byte ptr[ebp+ebx]
shl ecx, 16
movzx edx, byte ptr[ebp+edx]
shl ebx, 8
movzx eax, byte ptr[ebp+eax]
shl edx, 24
or ebx, ecx
or edx, eax
add esi, 4
or edx, ebx
sub nDivided_Width, 001h
mov byte ptr[edi-004h], edx
jnz short lopX
0124デフォルトの名無しさん
NGNG1次キャッシュに完全にヒットさせた状態で
>>86 が3.55クロック/ピクセル
>>122 が3.75クロック/ピクセル
くらい。
640×480ピクセル、ピクセルデータランダム、テーブルデータランダムだと、
>>86 が11.66クロック/ピクセル
>>122 が11.76クロック/ピクセル
くらいだった(ビデオメモリに転送せず、メインメモリ上で処理した場合)。
0125124
NGNGmov edx, Width
lopX:
movzx ecx, byte ptr [esi]
shl ecx, 8
movzx eax, byte ptr [edi]
mov al, [tbl+eax+ecx]
mov [edi], al
movzx ecx, byte ptr [esi+1]
shl ecx, 8
movzx eax, byte ptr [edi+1]
mov al, [tbl+eax+ecx]
mov [edi+1], al
movzx ecx, byte ptr [esi+2]
shl ecx, 8
movzx eax, byte ptr [edi+2]
mov al, [tbl+eax+ecx]
mov [edi+2], al
movzx ecx, byte ptr [esi+3]
shl ecx, 8
movzx eax, byte ptr [edi+3]
mov al, [tbl+eax+ecx]
mov [edi+3], al
add esi, 4
add edi, 4
sub edx, 4
jne lopX
0126デフォルトの名無しさん
NGNG0127
NGNG「EXEファイルはOSは理解するがCPUは理解しない」
APIでしか交信できない
.dll
.h
.lib
.drv
.VxD
.sys
.ocx
0128デフォルトの名無しさん
NGNGさぁ、どうなんだろうね?難しい質問だね。
答えが分かったら是非教えてね。
0130111
NGNGどこかミスってましたか?(^^;;;
確認してなかったので、申し訳ないです。m(_ _)m
と言う訳で、またまた確認してませんが、P6用に修正しました。
マニュアルしか読んでないので、本当に早いのか疑問はありますが…。
ループの外は何も考えてないので、適当に、その外に吸収してやって下さい。
(またまたEBPがテーブル)
mov edx, 0ff00ff00h
and edx, dwrod ptr [ edi+000h ]
mov ebx, 0ff00ff00h
and ebx, dword ptr [ esi+000h ]
shr edx, 8
mov eax, 000ff00ffh
or edx, ebx
sub nDivided_Width, 1
jz short lopX_END
lopX:
and eax, dwrod ptr [ esi+000h ]
mov ecx, 000ff00ffh
add esi, 004h
and ecx, dwrod ptr [ edi+000h ]
movzx ebx, dx
shl eax, 8
movzx ebx, byte ptr [ ebp+ebx ]
shr edx, 16
or ecx, eax
movzx edx, byte ptr [ ebp+edx ]
movzx eax, ecx
shl ebx, 8
movzx eax, byte ptr [ ebp+eax ]
shr ecx, 16
shl edx, 24
movzx ecx, byte ptr [ ebp+ecx ]
or eax, edx
add edi, 004h
shl ecx, 16
mov edx, 0ff00ff00h
or eax, ebx
and edx, dwrod ptr [ edi+000h ]
mov ebx, 0ff00ff00h
or ecx, eax
and ebx, dword ptr [ esi+000h ]
shr edx, 8
mov eax, 000ff00ffh
mov dwrod ptr [ edi-004h ], ecx
or edx, ebx
sub nDivided_Width, 1
jnz short lopX
0131111
NGNGlopX_END:
and eax, dwrod ptr [ esi+000h ]
mov ecx, 000ff00ffh
and ecx, dwrod ptr [ edi+000h ]
movzx ebx, dx
shl eax, 8
movzx ebx, byte ptr [ ebp+ebx ]
shr edx, 16
or ecx, eax
movzx edx, byte ptr [ ebp+edx ]
movzx eax, ecx
shl ebx, 8
movzx eax, byte ptr [ ebp+eax ]
shr ecx, 16
shl edx, 24
movzx ecx, byte ptr [ ebp+ecx ]
or eax, edx
shl ecx, 16
or eax, ebx
or ecx, eax
mov dwrod ptr [ edi+000h ], ecx
0132デフォルトの名無しさん
NGNG全角アルファベットあたりがかなり難解。
013364
NGNGそろそろ終了か!?
0134124
NGNGコードのアライメントによって微妙に変わってくるね。当たり前だけど。
PentiumIIではほとんど同じ速度みたい。
>>130も>>122や>>86より速いということはなかった。
0135デフォルトの名無しさん
NGNG0136デフォルトの名無しさん
NGNGマジで言ってるのかなー?
CPUはマシン語以外理解できないと思うんだけど。
0137デフォルトの名無しさん
NGNG0138デフォルトの名無しさん
NGNG0139デフォルトの名無しさん
NGNG0140デフォルトの名無しさん
NGNG■ このスレッドは過去ログ倉庫に格納されています