==処理を早くする==
■ このスレッドは過去ログ倉庫に格納されています
0001名無しさん@お腹いっぱい。
NGNGとりあえずif文を減らす、比較対象を0にする、代入を減らす
位しか思いつかないのですが
今圧縮解凍をやっています
初心者なので難しい話にはついて逝けませんが
皆さんの経験を圧縮解凍に限らず語ってください
0002名無しさん@お腹いっぱい。
NGNGそういうレベルの話をする前に、
アルゴリズム的なことはちゃんと考えているか?
0003名無しさん@お腹いっぱい。
NGNGまあ、アルゴリズムとも言えるが、良い例が出ているので。
http://piza.2ch.net/test/read.cgi?bbs=tech&key=965775993
0004名無しさん@お腹いっぱい。
NGNGmalloc()、reallc()をやめて、なるべく再帰で組むとか、
qsort()やhashを使うとか、ソートやデータの入れ替えも
実体に対して行わず、なるべくポインタに対して行う
とかやったけど、最近はどうなのかな? ふぅ。
0005名無しさん@お腹いっぱい。
NGNG0006名無しさん@お腹いっぱい。
NGNG0007名無しさん@お腹いっぱい。
NGNG圧縮が早い方が良いのか
展開が早い方が良いのか
それとも平均的な方が良いのか
圧縮率を下げても速度重視なのか、
またはその逆なのか、
動的に調整できるべきなのか
小手先のテクニックは目的から方法を選んでから
0008名無しさん@お腹いっぱい。
NGNG00098
NGNG0010名無しさん@お腹いっぱい。
NGNGintelのP6アーキテクチャーだと、効果が無い場合が多いから気をつけること。
勿論、効果がある場合もあるが。。。。
(RSB:Return Stack Buffer)
>>9
なにそれ?
00119じゃないけど
NGNG80対20の法則だったか、、、
全コードの内20%が性能の80%を出すとかだったような、うろ覚え。
プログラム以外でも、何故かたいてい当てはまる不思議な法則
0012名無しさん@お腹いっぱい。
NGNGプログラムの20%のコードが全体の80%のCPU時間を消費するとか
20%の社員が全社の80%の利益を生むとか
20%のプログラマがプロジェクトの80%のバグを生むとか
昔はやったマーフィーの法則にも乗ってた尾
0013名無しさん@お腹いっぱい。
NGNG0014名無しさん@お腹いっぱい。
NGNGプログラムな可能性が高し。そこまで重いルーチンがあれば
そこだけは気合をいれて高速化しておくべき。結果一箇所に処理負荷
が集中することはなくなる。
0015名無しさん@お腹いっぱい。
NGNG0016>14
NGNG君はすごい人だな(w
0017名無しさん@お腹いっぱい。
NGNG・再起を使わない
・ループを展開する
・div()などを使う
・関数などは展開する
・データなどを変換しないように作る
・使用頻度の高い関数などをアセンブラにする
・etc...
0018名無しさん@お腹いっぱい。
NGNG速いと思ってるぢぢゐが・・・
0019名無しさん@お腹いっぱい。
NGNG書いたアセンブラは速いよ
よくて倍ぐらいの速度しか出ない気はするけども。
0020>18
NGNGコンパイラの進歩はそんなに進んでないって事だね。
0021名無しさん@お腹いっぱい。
NGNG何重にも掛けていますから、それで余計に遅いです。
0022>18
NGNGでも、アセンブラじゃなきゃ表現出来ない事も多いよ。
たとえば
1)CF(キャリーフラグ)OF(オーバフロー)を使う
2)実行番地の保存(コルーチンとか簡易並列処理)
0023名無しさん@お腹いっぱい。
NGNGちみは逆アセしたコードとか見た事あるの?
0024引用くん
NGNGvoid Excpy_memcpyclip(UBYTE *pbDst@` UBYTE*pbSrc@` int iSize)
{
//pbSrcからpbDstに0以外の値をコピーする。
for(; iSize>0 ; iSize--@` pbSrc++@` pbDst++)
{
if(*pbSrc != 0)
{
*pbDst = *pbSrc; //0以外の値をpbDstに描き出す
}
}
}
改善前
extern void Excpy_imemcpyclip(UBYTE *pbDst@` UBYTE *pbSrc@` int iSize);
#pragma aux Excpy_imemcpyclip=\
" test ecx@` ecx"\
" jz quit"\ //0だったら抜ける
" again: mov al@`[edx] "\ //alにpbSrcの色データを入れる
" test al@`al "\ //if(*pbSrc == 0)
" je check "\
" mov [esi]@`al "\ //*pbDst=*pbSrc 0以外なので書きだす
" check: "\
" inc edx "\ //pbSrc++
" inc esi "\ //pbDst++
" dec ecx "\ //iSize--
" jnz again "\ //iSize!=0の間はループする
"quit: "\
parm [esi][edx][ecx] modify [al esi edx ecx];
改善後
pbSrcから32Bitレジスタへ一気に4バイト読み込んで、メモリアクセス回数を4分の一に減らす。
extern void Excpy_imemcpyclip(void *pBuffer@`void const *pSorce@` int const iSize);
#pragma aux Excpy_imemcpyclip=\
"mov edi@`ecx"\
"shr edi@`2"\
"test edi@`edi"\
"jz loop1"\
"again4: mov ebx@`[eax] "\
" test bl@`bl "\
" je check1 "\
" mov [esi]@`bl "\
" check1: "\
" test bh@`bh "\
" je check2 "\
" mov [esi+1]@`bh "\
" check2: "\
" lea eax@` [eax+4] "\
" shr ebx@` 16"\
" test bl@`bl "\
" je check3 "\
" mov [esi+2]@`bl "\
" check3: "\
" test bh@`bh "\
" je check4 "\
" mov [esi+3]@`bh "\
" check4: "\
" dec edi"\
" lea esi@`[esi+4]"\
" jnz again4 "\
"loop1:"\
"mov edi@`ecx"\
"and edi@`3"\
"test edi@` edi"\
"jz quit"\
"again: mov bl@`[eax] "\
" lea eax@`[eax+1]"\
" test bl@`bl "\
" je check5 "\
" mov [esi]@`bl "\
" check5: "\
" dec edi"\
" lea esi@`[esi+1]"\
" jnz again"\
" quit: "\
parm [esi][eax][ecx] modify [bl edx eax edi esi];
改善前は486DX-33MHzで30f/sでしたが改善後は90f/sとなり3倍高速になりました。
002518
NGNGまず、486とかで「速くなったよ」はがぢぢゐだと逝っておこう。
>19、20
最近のプロセッサ用に、アウトオブオーダー実行やディレイドブランチで
パイプラインを乱さないように最適化されたコードより速いコードをアセンブラ
で書くのは、無理です。
>21
それは、クラスライブラリの呼び出し部分をアセンブラで書く話ですか?
それとも、クラスライブラリをアセンブラで書きなおす話ですか?
どちらにしても、アセンブラ以外で書いた自前のライブラリに置きかえれば済むことです。
>22
ワタシが18で書いたのは実行速度の事です。
「だからアセンブラで書いたほうが高速だ」という話である事を説明してください。
>23
MSCのVer5くらいまでは、コンパイラの吐いたコードを手直しして高速化する
ような事はしょっちゅうやってました。
そもそもワタシは8080のアセンブラからプログラムをしています。
>24
古いCPUの例を出すんなら、MSCあたりで、hugeポインタを扱う
コードとかだしたらどうですか?当時なら1ケタ違う例が出せますよ(藁
0026名無しさん@お腹いっぱい。
NGNG0027名無しさん@お腹いっぱい。
NGNGまぁ、「これで効果的な高速化が出来る場合もある」ってのはいろいろあるもんですね。
まぁ、どれもいっぱーい廻るループの内側ならそこそこ効果あるんでしょうね。
002822>25
NGNG私も同じ趣旨ですよ。
>「だからアセンブラで書いたほうが高速だ」という話である事を説明してください。
たとえばCでスマートに書けるならCで書いて不満が出るような事は無いでしょう。
ただ、Cの範囲ではスマートに書けない事があって、その場合は
アセンブラを併用した方が速いという意味で書いたつもりです
たとえば多倍長処理とかやっぱりキャリーを見たいでしょう?
002922
NGNG>アウトオブオーダー実行やディレイドブランチで パイプラインを乱さないよう
>に最適化されたコードより速いコードをアセンブラ で書くのは、無理です。
私はDSPも書きますが、手間はかかりますが、やっぱり性能を出すには
それでもやらなければならない事がありますよ。
といってもDSPの場合の最内ループは比較的単純ですけどね。
コンパイラよりは何割かは頑張れますよ
0030名無しさん@お腹いっぱい。
NGNG0031名無しさん@お腹いっぱい。
NGNG0032>
NGNG0033名無しさん@お腹いっぱい。
NGNG0034名無しさん@お腹いっぱい。
NGNG日本でもアナリストやコンサルタントがもてはやされるようになって
きたのは、このあたりまえの事実に気付く人がようやく増えたから。
003518>33
NGNG0036名無しさん@お腹いっぱい。
NGNGasm命令使わなくっても出してくれるの?
0037>1
NGNGqsortを使わない>ソートを使わなくてすむ実装を考える
doubleは極力使わない>固定小数点を使う
sin等の関数も使わない>テーブルを参照する
malloc等の速度を計測する>必要に応じてwwwに転がっている高速なやつを使う
strchr等の関数を計測する>必要に応じて以下同文
Cの範囲では、このくらいまで可能と思います
0038名無しさん@お腹いっぱい。
NGNG使わないでしょ。
P6コアのFPUの場合、コンパイラは整数と浮動小数点レジスタがエイリアスされて
いるだけでPORT0以外で並列処理されることを見落としてレイテンシ計算を短く見
積もってくれたりもしますから。後P5コアだとfxchがポストフィックス扱いになる
ことも注意点ですね。
0039名無しさん@お腹いっぱい。
NGNG1には理解できない領域に突入してる事は確かだろうが(藁
004039
NGNG0041名無しさん@お腹いっぱい。
NGNG0042名無しさん@お腹いっぱい。
NGNGインテルの本とかも、WEBにあるから、そーゆーのみればーー
0043名無しさん@お腹いっぱい。
NGNGと思う。すでにプロファイル済み。
1)並列処理を出来るように考える
CPUのレジスタ長が32bitとか64bitあるので並列に処理させられるように
考えるとN倍になる。
2)とにかく検索が高速になるよう「表引等」工夫する
3)アセンブラを視野に入れて、キャリーを使うアルゴリズム
シフトだけでなく回転等も使えると考えて最適化を考える
で、インラインアセンブラを使う事を厭わない
4)とにかく本人がコンピュータ本だけでなく数学物理迄色々勉強する
雑学知識が案外アルゴリズム作成に役立つ
0044名無しさん@お腹いっぱい。
NGNGPentium3で速度が上がりました
でも遅くなったと言う人がいます
Athlonでは遅くなりました
要するにターゲットを何にするかも決めずに
最適化がどうのといったところで話しにならん
机上の空論の前にアルゴリズムを見直せ
0045名無しさん@お腹いっぱい。
NGNGアプリではアセンブラも現役
004638
NGNGfld [memory]
はPORT2で実行されますから実質0クロック扱いにすること、
fadd st@`st(1)
fxch st(2)
は実行順番が
fxch st(2)
fadd st(2)@`st(1)
と入れ替わりストールの条件が変化するといいたかったわけです。
0047名無しさん@お腹いっぱい。
NGNGesiとedi使ったときで速度が違うって聞いたよ>AMD
アルゴリズムでどうにかなるのかな
まあ、アセンブラ使うんだったら、各CPUごとにコード書くんだろうなあ
0048名無しさん@お腹いっぱい。
NGNGREP MOVSD
吐いてるのを見た事無いんだけど、
こういうの使いたければアセンブラ必須ですよね?
>47
例えば、インテルではストールしないけど、AMDだとストールしてしまう
みたいなのってあるんですかねぇ?
AMDのCPUの仕様が知りたい。どっかにないですか?
004948(連カキコ)
NGNGESIとかEDIレジスタをあんまり使ってくれないのは、
気のせいかな?
0050>38
NGNGアセンブラで書いたコードの比較きぼっ
0051>48
NGNG; 12 : memcpy(pDest@`pSrc@`nSize);
mov ecx@` DWORD PTR _nSize$[esp-4]
push esi
mov esi@` DWORD PTR _pSrc$[esp]
mov eax@` ecx
push edi
mov edi@` DWORD PTR _pDest$[esp+4]
shr ecx@` 2
rep movsd
mov ecx@` eax
and ecx@` 3
rep movsb
pop edi
pop esi
0052名無しさん@お腹いっぱい。
NGNGVCやVSについてるんですか?
教えてください。
0053FBI職員
NGNGこれをプロファイリングといいます。
005447>48
NGNG>みたいなのってあるんですかねぇ?
午後のこ〜だの作者のとこに少しだけ
ttp://homepage1.nifty.com/herumi/adv/adv30.html
>AMDのCPUの仕様が知りたい。どっかにないですか?
ここかなぁ
ttp://www.amd.com/support/techdocdir.html
005550>38
NGNG{
*p3 = p1[0]*p2[0] + p1[1]*p2[1] + p1[2]*p2[2] + p1[3]*p2[3]
+ p1[4]*p2[4] + p1[5]*p2[5] + p1[6]*p2[6] + p1[7]*p2[7];
}
これを gcc -O9 -mpentiumpro -march=pentiumpro -ffast-math -S
でコンパイルすると
mov eax@`p1
mov edx@`p2
fld dword ptr [edx]
fld dword ptr [edx + 4]
fxch st(1)
fmul dword ptr [eax]
fxch st(1)
fmul dword ptr [eax + 4]
faddp
fld dword ptr [edx + 8]
fmul dword ptr [eax + 8]
faddp
fld dword ptr [edx + 12]
fmul dword ptr [eax + 12]
faddp
fld dword ptr [edx + 16]
fmul dword ptr [eax + 16]
faddp
fld dword ptr [edx + 20]
fmul dword ptr [eax + 20]
faddp
fld dword ptr [edx + 24]
fmul dword ptr [eax + 24]
faddp
fld dword ptr [edx + 28]
fmul dword ptr [eax + 28]
faddp
mov ecx@`p3
fstp dword ptr [ecx]
こうなりました。
手作業で最適化するとPentiumPro用だと
mov EAX@`p1
mov EDX@`p2
fld dword ptr [EAX + 0*4]
fmul dword ptr [EDX + 0*4]
fld dword ptr [EAX + 4*4]
fmul dword ptr [EDX + 4*4]
fld dword ptr [EAX + 1*4]
fmul dword ptr [EDX + 1*4]
fld dword ptr [EAX + 2*4]
fmul dword ptr [EDX + 2*4]
fld dword ptr [EAX + 3*4]
fmul dword ptr [EDX + 3*4]
fld dword ptr [EAX + 5*4]
fmul dword ptr [EDX + 5*4]
fld dword ptr [EAX + 6*4]
fmul dword ptr [EDX + 6*4]
fxch st(4)
faddp st(6)
fld dword ptr [EAX + 7*4]
fmul dword ptr [EDX + 7*4]
fxch st(3)
faddp st(5)
faddp st(5)
faddp st(3)
fxch st(1)
faddp st(3)
faddp
mov EAX@`p3
faddp
fstp dword ptr [EAX]
こうなります。fldをレイテンシ計算からはずしているところが味噌です。
ただしスタックが深いためDOS窓が開いていると頻繁にタスクのスイッチング
が入るようでレジスタの退避に時間がかかってかえってスピードが落ちます。
0056名無しさん@お腹いっぱい。
NGNGfld;fmulは同時実行できるが
faddpが間に入るとダメってこと?
fld;fmul
faddp
fld;fmul
faddp
とはいかないってことなのかな。
それとも後半に秘密が?
005756
NGNGlong *a@` *b;
a[i+0] = b[i+0];
a[i+1] = b[i+1];
a[i+2] = b[i+2];
a[i+3] = b[i+3];
とするより
a[i+4] = b[i+4];
a[i+1] = b[i+1];
a[i+2] = b[i+2];
a[i+3] = b[i+3];
って感じで一度16バイト先をアクセスしておくと、
キャッシュフィルの関係で速くなる
FPの計算でも使えるんじゃないかな。。
0058>57
NGNG0059名無しさん@お腹いっぱい。
NGNGaが16バイト境界に配置されてるとしたら、どっちも一緒の気がするです・・・
むしろ、キャッシュへの転送が終わる前にアクセスできる可能性を考えると
アタマからアクセスしたほうが早いような気も…
0060>52
NGNGVC++のPro版以上についてる。
006157>59
NGNG前述の手法は16バイト境界に配置されていないと意味がありません。
一度+16バイトをアクセスしておくと、キャッシュのモジュールが
そこから16バイトをフィルし始めます(+16〜+31)。その間CPUは
+4〜15のデータ処理し、CPUがそれらを処理し終わった頃には
+20〜+31のキャッシュフィルが終わっているので、CPUそれらの
データをキャッシュからアクセスできるので、高速になります。
順順にアクセスした場合+4〜+15のキャッシュモジュールが
メモリからフィルするよりもCPUの方が速いので(当たり前。
そのためにキャッシュがある)、CPUは待たされてしまいます。
0062名無しさん@お腹いっぱい。
NGNGを調べてくれます。さらにvc++にはありませんがgccやいくつかの
コンパイラはプロファイラの出力を再度読み込んで、その情報を元に
オプティマイズする、という機能もあります。
手間がかかりますが、2〜5割速くなります。もちろん人間のオプティマイズ
には及びませんが、広大なプログラムを漠然と(笑)速くするのにはある程度
効果があります。
006359>61
NGNGa[i+4] = b[i+4];
a[i+0] = b[i+0];
a[i+1] = b[i+1];
a[i+2] = b[i+2];
a[i+3] = b[i+3];
だと思ったので・・・
006463(途中でおしちった)
NGNGすると、処理が終わるのはj+3までキャッシュに入る時間で決まるので一緒
ではないか、と。
つまり、>>57はj+0〜j+7までアクセスするっていう事ですよね?
006561>64
NGNGa[0] = b[0];
for (i = 0; i < 256 - 4; i += 4) {
a[i+4] = b[i+4];
a[i+1] = b[i+1];
a[i+2] = b[i+2];
a[i+3] = b[i+3];
}
a[i+1] = b[i+1];
a[i+2] = b[i+2];
a[i+3] = b[i+3];
といったパターンのように連続して演算する場合です。
上記はメモリコピーですが、原理的には他のパターンにも
当てはまります。FreeBSDのカーネル内のbcopyとかに
使われています。
0066名無しさん@お腹いっぱい。
NGNG0067>66
NGNG0068>67
NGNGメモリ32MでNT動かしてて スワップしまくっててすげい遅くてさ
テストで32M増設するだけで10倍ぐらいの速度になるのにさ
プログラム直せっていわれたり(TT
32Mのメモリぐらい 俺が自腹切って買うから付けてくれって思う(TT
0069>68
NGNGjmp far [プログラマ板]
■ このスレッドは過去ログ倉庫に格納されています