1 :
デフォルトの名無しさん :
04/05/28 22:00 どうぞ
2 :
デフォルトの名無しさん :04/05/28 22:02
3 :
デフォルトの名無しさん :04/05/28 22:07
またこの手のスレか またこの手のスレか
VC++6.0SP6用のProcessor Pack早くだせよヴォケ
速くしろよ
/arch:SSE2
アセンブラスレでいいだろ
すぐにアセンブラって言出す奴はアレだな インテルのコンパイラなんかには C++のライブラリが含まれているがな。
12 :
デフォルトの名無しさん :04/05/30 00:08
VC Toolkit 2003 で効率よくSSE2使うコツを話そうぜ。
15 :
デフォルトの名無しさん :04/10/19 06:28:21
16 :
デフォルトの名無しさん :04/10/23 07:26:59
SSEを使った簡単なプログラムを教えてください。 たとえば1+2はどのように書けばよいのでしょうか?
SSE3のスレかと思ったぜ
SSE3って何が新しいの?っていうか普及すんの?
19 :
EXCULTer's / Active metropolis ◆/80RBXpvJA :04/11/12 05:14:46
MASM32w
20 :
デフォルトの名無しさん :04/11/22 16:09:13
21 :
デフォルトの名無しさん :04/12/08 08:53:11
MMXを使用してフルカラーの画像を拡大縮小するルーチンを書きたいのですが、 どっかに手頃なソースは落ちてないもんでしょうか。 できれば品質ではなくスピード重視のものがいいのですが。
どうもここら辺が都合が良さげなので調べてみます。
> SDL_Surface * zoomSurface (SDL_Surface *src, double zoomx,
> double zoomy, int smooth);
> Zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface.
> 'zoomx' and 'zoomy' are scaling factors for width and height. If 'smooth' is 1
> then the destination 32bit surface is anti-aliased. If the surface is not 8bit
> or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly.
http://www.ferzkopp.net/~aschiffler/Software/SDL_gfx-2.0/
中身除いてみたらMMX使ってなかったよ... orz 自分で勉強しなきゃ駄目なのかな、とほほ...
MMXの解説読んでみたら、画像の拡大縮小には MMXの命令セットは使えそうにもない事が 判明しました。どうすればいいんだ...orz
おお、いつの間にかレスが! ありがたや、ありがたや。 早速試してみます。
27 :
デフォルトの名無しさん :05/02/21 12:55:29
MMXでDWORDにアンパックしたやつをDWORDで乗算させるにはどうしたらよいんですか? pmulはWORDしか対応していないようなので… 誰か助けてください
28 :
デフォルトの名無しさん :05/02/21 14:44:56
>>27 ヒント
a, b, c, d は16bitの整数で
X = a * 2^16 + b
Y = c * 2^16 + d
とおくと、
X * Y
= (a * 2^16 + b) * (c * 2^16 + d)
= (a*c * 2^32) + ((a*d + b*c) * 2^16) + b*d
あとはお好きなように。
29 :
デフォルトの名無しさん :05/02/21 14:46:24
あ、^はXORじゃなくて累乗ね
素直にシフト使って書けばそんな断りもいらなさそうなものだが。
>>28 ありがとうございます。
おちついて調べてみたら、DWORDではなくWORDの乗算でした…
WORDならなんとかなりそうです。
>>25 再upして頂く事は出来ませんでしょうか・・・
33 :
デフォルトの名無しさん :2005/07/07(木) 12:01:11
SSEへの最適化のための構造体のアライメントってどうやって調べるのでしょうか?
ヒント: offsetof
>>33 テキトーにベンチマークプログラム書いて調べるとかw
4kB境界に合わせればほぼ確実に最適だと思う
3D NOW!使ってるヤシいる? 俺はIntelCPUなのでMMXやSSEしか使ったことがないが。
>>36 ノ
pfacc系がとっても便利で気に入っている。
>>37 上位と下位の加算か!
いいなあ。MMXやSSEでは使えないもんな。
SSE3には入ったみたいだけど。
自分の環境だと初代SSEまでしか使えないorz 新しいコアのAthlon買うかねぇ。 SSEで内積やる時に各積の加算ってどうやってる? 面倒なんでインラインから抜けて普通に書いちゃってるんだけど。
>>39 内積やってないけど、抜けたらせっかくのインラインが遅くならない?
俺ならシャッフルして2つ同時に足すかな。
xmm0=(a,b,c,d), xmm1=(e,f,g,h) として、
movaps xmm2, xmm0
shufps xmm0, xmm1, hoge
shufps xmm2, xmm1, hoge
するとこうなる。
xmm0=(e,f,a,b), xmm1=(g,h,c,d)
で、addpsやって同じようにもう1回足せば出るかな。
面倒なのでここまで。すまぬ。
やっぱり続き。 movaps xmm2, xmm0 shufps xmm0, xmm2, hoge addps xmm0, xmm2 これでOKか?試してないけど。 xmm0=(?,e+f+g+h,?,a+b+c+d) となるはず。
>>40-41 なるほど。自分ではこんなん考えてみけどどうだろう。
movaps xmm2, xmm0; xmm2 = (a,b,c,d) xmm0 = (a,b,c,d) xmm1 = (e,f,g,h)
unpcklps xmm2, xmm1; xmm2 = (g,c,h,d)
unpckhps xmm0, xmm1; xmm0 = (e,a,f,b)
addps xmm0, xmm2; xmm0 = (e+g, a+c, f+h, b+d)
movhlps xmm1, xmm0; xmm1 = (c, d, e+g, a+c)
addps xmm0, xmm1; xmm0 = (c+e+g, a+c+d, e+f+g+h, a+b+c+d)
movlps [dst], xmm0; 下半分だけ取り出す。
なるほど、規則的なシャッフルならアンパックの方がきれいだね。 簡単なコード書いて速さの測定でもしてみるか。
まあどっちにしろストールするような気がするけどねorz 2回連続のシャッフルないしアンパックをどうにかしてばらせないかなぁ
Intelのページに、SSE3を使わないコードと使うコードの例が載ってた。 mulps xmm0, xmm1 movaps xmm1, xmm0 shufps xmm0, xmm1, 0xb1 addps xmm0, xmm1 movaps xmm1, xmm0 shufps xmm0, xmm0, 0x0a addps xmm0, xmm1 これは1個ずつやっているな。 mulps xmm0, xmm1 haddps xmm0, xmm0 haddps xmm0, xmm0 SSE3はすごいなあ。同じhaddpsを続けただけでできてしまう。 ていうか3D Now!もそうか。K6-2が、はまればすごく速かったのがわかる気がした。 ただ、Prescottではhaddpsのタイミングが13-4なんだよな。 上のコードに7+13+13 = 33clkもかかる。 Athlon64だとhaddpsが5-2、mulpsが5-2。5+5+5 = 15clkかな。 ただ、Pen4ならこの33clkのブロック自体を何個も並列に実行しそう。 2個同時でも haddps xmm0, xmm1 haddps xmm0, xmm0 これでOK。何者だよっていう簡単さだな。 内積を、どう利用するかによって、移動命令で欲しい形式に落とすのも腕の見せ所。
>>45 やっぱ要素間演算がないのは皆不満だったらしいね。
便利だけど自分の環境じゃ試せないのが痛いなぁ。
にしてもSSE3は便利なのはいいけどホント遅そうだ。
そんなに遅くはないんじゃない? Prescottはもう死にかけのアーキだし、K8なら速いし。 YonahのSSE3も速くなってると思う。
そうかぁ。やっぱSSE3使ってみたいなぁ。 この夏に新しい石のAthlonでも買って試してみるか。 まあPrescottでも流れれば速いのかな?
>>48 うん、流れたときの速さは比べるものがないほどだと思う。
リアル128bitでバラバラに動くSIMDは強力。
レジスタ間movapsのレイテンシが6なことなど気にならない。
最悪だ・・・ノートのバッテリーが逝ってしまわれた・・・金が・・・ SanDiegoもVeniceもさようなら〜orz
51 :
デフォルトの名無しさん :2005/08/25(木) 14:50:35
sse3の使えない環境でsse3を使ったプログラムを走られたらどうなりますか?
Illegal Instruction例外で落ちます。
>>51 bochsという強力なエミュなら、どんな環境でもSSE,SSE2,SSE3,x64,3dnowなど
なんでもエミュレートできるぞ。
どんな環境でもって言うのはPowerPCでもSPARCでもってこと。
人いない・・・
ほんとにいませんねえ。 今までにSIMDで何を作ったことがあるか書いていくか?
行列の掛け算・・・・
いまから拡張命令使ってFirefoxを最適化してみようと思う。
[word data1][word data2][word data3]・・・ [word data100][word data101][word data102]・・・ こんなふうに並列演算したいデータがメモリ上に並んでいない場合 data1とdata3とdata100とdata102を並列計算したい時って pinsrw でデータを集める以外にうまいやり方ってない? movq でメモリから64bit取り出してパックしたほうが早いかな?
まずはデータ構造を見直せ。 すべてはそこからだ。
データ構造はCCDのRAWデータだから仕方ないよ [R][G][R][G] [G][B][G][B] という配列(今回扱うのは1画素12bit)
SSEの整数命令って単にMMX命令のオペランドに MMXレジスタだけじゃなくてSSEレジスタも使えるようになったってだけ? しかも64ビットまでしか使えないって罠で利点はemmsなしでOKってだけ? ここからチラシの裏 FirefoxのビルドしたらAthlonノートでやけどしたw しかし最適化といってもどこから手を付けていいのやら。 テテさんとかどうやってんだろうね。
>>61 SSE整数は128bit使ってるよ。
ただ、現状ではMMXが速いことが多いけど。
将来的には演算器が強化されてSSEの方が速くなるだろうし、
x64ではレジスタが倍の16本に増えるというメリットもある。
SSE2じゃそうだろうけど初代SSEでもできんの?
はやくSSEのスループットが1にならないかなー。
SSEの演算器だけ倍速作動とかw
ある程度トランジスタ割けば、SSEユニットを倍積めるんだろうか。 単純に演算器の数を倍にするの。
>>61 チラシの裏
MMXのmovqを使ってメモリコピーを高速化してるよ。
SSE系は使ってないみたい。
現状じゃ128bitのロード・ストアは遅いもんな。 Pen4だけは128bitの方が速いけど、 これも幅が広いから小回り効かなくて遅いのかな。
packed byteな乗算命令がなくて(´・ω・`)ショボーン
俺は多倍長データ加算用のSIMD命令がほしい。
勝手に3D NOW!!に対応してくれるコンパイラ無いかな。
CQ出版が15日に出す本が良本ならこのスレも 盛り上がってくれることを信じつつwktk
微妙な本だな。大体一章が10ページくらいのB5判だから、 基本的な触りくらいしか出てないようなヨカソ インテルのマニュアルの方がよっぽど詳しいのではなかろうか。
>>75 そら純正マニュアルに敵う本なんてまずないだろ……
早速買って来たよ。 SSE2の日本語+絵による解説は使えそう。
altivecはここじゃだめですか
iccでemmintrinつかってるんですが、 __m128 <-> __m128dのキャストをインラインアセンブリ 使わずにできます? 倍精度の仮数部の一部を整数演算で0クリアしたいんです。
_m128iを引数とする関数で_m128dをそのままの形で使いたいって事でOK? __m128d a; __m128i b; b = _mm_and_si128(*(__m128i*)&a,b);
>>82 メモリアクセスするコードが生成されないか心配。
んじゃこっち union { __m128d a_d; __m128i a_i; } __m128i b; (ry
助言あんがと。 s=_mm_cvtpd_ps(d); d=_mm_cvtps_pd(s); てなことを d=_mm_and_si128(d,mask); てな感じで済ませたかったけど、 union使って書くと遅くなったんで最適化してくれないっぽ… 入力がfloatの範囲を越えても動かしたいんだけどなぁ
インラインでガリガリ書くしかなくね?
なるべくアセンブリは避けたかったですが、 inline __m128d round(__m128d d,__m128i mask){ __asm__ __volatile__ ("pand %1,%0" : "+x"(d) : "x"(mask)); return d; } で少し速くなりました。 どもども。
720*480のBMPを640*480に縮小するのにMMXを使えないか思案中。
640*480側で8ピクセル(24byte=MMX*3)ずつやればいいかな。 720*480側は普通に読むのと3byteずらして読むのをやって 掛け算で加重して・・・あ、MMXの乗算は16bitだけか。 どのくらいの速度になるだろ。
久しぶりだったから配列のアドレスをmovでeaxに入れようと四苦八苦してしまったorz 今からbmpの構造を思い出そうとしている俺は完全に出遅れかな?
>88 バイリニアをMMXで実装するだけ。 しかも480で縦ライン固定なら1時間くらいで出来るんじゃね?
//横のドット数が9と4の倍数の24bitBMPに対し、横を8/9に縮める void resize(unsigned char *p,int w,int h) { int i,j,k,n; n=w/9*h; for (k=0; k<n; k++){ for (j=0; j<8; j++){ for (i=0; i<3; i++){ p[(k*8+j)*3+i]=((8-j)*p[(k*9+j)*3+i]+(1+j)*p[(k*9+j+1)*3+i]+4)/9; } } } } 9ピクセル*n回の処理。まずCで書いて動作することを確かめた(もはや十分な速度だな・・・)。 MMXもこれと同じ方針で行く。 MMXには除算命令がないので乗算で代用。 精度も16bitだから、8bitの数値に対してはほとんど問題ない。 MMX版のコードは、次のように設定して次レスのコードをn回ループさせる。 short m[48]={8,8,8,7,7,7,6,6,6,5,5,5,4,4,4,3,3,3,2,2,2,1,1,1,1,1,1,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,8,8,8}; n=w/9*h; eax=m、esi=edi=p mm5={4,4,4,4} ;=9/2 mm6={7282,7282,7282,7282} ;=10000h/9 mm7={0,0,0,0} 速度は、素通し(HDDのBMPをコピーするだけ)が156ms、MMXが175ms、C版が241ms。 720*480のBMPを5個変換するのにかかった時間(PentiumM)。 まあ、ディスクキャッシュにヒットしなかったら、ずっと遅くなるけど。 本来なら非SIMDアセンブラとの比較もしたいところだが、ここまで。 3個の出力を調べて、MMX版とC版の出力は全て一致していた。
xor ecx,ecx lp0: movq mm0,[esi+ecx] movq mm1,mm0 punpcklbw mm0,mm7 punpckhbw mm1,mm7 pmullw mm0,[eax+ecx*2] pmullw mm1,[eax+ecx*2+8] movq mm2,[esi+ecx+3] movq mm3,mm2 punpcklbw mm2,mm7 punpckhbw mm3,mm7 pmullw mm2,[eax+ecx*2+48] pmullw mm3,[eax+ecx*2+48+8] paddw mm0,mm2 paddw mm1,mm3 paddw mm0,mm5 paddw mm1,mm5 pmulhw mm0,mm6 pmulhw mm1,mm6 packuswb mm0,mm1 movq [edi+ecx],mm0 add ecx,8 cmp ecx,24 jnz lp0 add esi,27 add edi,24 ;MMXでバイリニアてのはどうやるの?
>>90 変数の中身へのポインタを取得するとアセンブリでは
lea eax,[esp-12]
のようになるから、movは使えないのだね。
int *a;ならmov eax,aできても、int a[4];だとmov eax,aで氏んだからな。
あのときはけっこう悩んだ。
SIMDで計算したいブロックを高級言語で明示できないかな。 たとえば、C言語風の妄想言語... struct complex_t { float r, i; }; foo() { complex c[4]; VEC( float re : [ c[0].r, c[1].r, c[2].r, c[3].r ], float im : [ c[0].i, c[1].i, c[2].i, c[3].i ] ) { float t = re * re - im * im; im = 2 * re * im; re = t; } とか書くと、VECブロックの中が自動的にSIMD命令で構成される。 ( SIMD未対応のCPU向けのときは、通常の命令になる ) SIMDで実行するのだから、VECブロック中には分岐はかけず、 ループも固定回数ループだけ。 どう?この妄想言語。
1つの構造体がメモリ上でバラバラになってるな。 それはいいとして、組み込み関数と演算子オーバーロードでよくない? ただ、俺もそういう言語は欲しいと思っていた。 せっかくCPUに色々な命令があるんだから、命令が見える言語がいいよね。 そういう意味じゃCのシフト演算子とかナイスと思った。
Intrinsics使えばインジャネ? 最終段で機械任せの最適化するなら、 そのままCでも構わないと思うけど。
8bitビットマップ(グレースケール)から32bitビットマップへの変換を、MMX使って 実装しようとしているのですが、思っていたよりも早くならずに難渋しています。 適当なやり方しているのは自覚しているのですが、同じく適当にCで書いたルーチン と、リリース版の最適化コミで速度変わらずってのはかなり凹みました。 どこかもっと最適化する場所があるのでしょうか? ご存じの方ご教授願います。 void testcopy( void *dst, const void *src, int size ) { int size2 = size >> 1; if(size2 != 0){ __asm{ mov edi, dst; mov esi, src; mov ecx, size2; loop_mp: movq mm0, [esi]; punpcklbw mm0, mm0; punpcklbw mm0, mm0; movq [edi], mm0; lea esi, [esi + 2]; lea edi, [edi + 8]; dec ecx; jnz loop_mp; emms; } } }
>>100 使用CPUは何?
lea esi, [esi + 2] はadd esi,2 のが無難だと思う。Pen4ならaddのが速い。
movqは8byteだから最後の2byte読むときに6byte余計に読んでしまうのが気持ち悪い。
速度の面からも、読み取りを2byte毎じゃなく4byteか8byteにするべき。
MMX2が使えるならpshufwを使ってもいいかな。
movd mm0, [esi];
punpcklbw mm0, mm0;
movq mm1,mm0
punpcklbw mm0, mm0;
punpckhbw mm1, mm1;
movq [edi], mm0;
movq [edi], mm1;
add esi,4;
add edi,16;
sub ecx,2;
jnz loop_mp;
即興で作って試してないけど、こんなのでどうでしょ。
102 :
100 :2006/02/17(金) 21:25:43
>101 >使用CPUは何? 書き忘れていました。CPUはPen4ですが、諸事情(VC6sp6開発)のため MMXまでの制限になってます。
そういえば、これ処理が軽いからメモリ速度がボトルネックになるね。
おそらくCで書いたルーチンでもメモリ帯域を使い切っているに近いと思う。
ありえん話だが、メモリがL1キャッシュくらい速い環境ならば
>>100 氏はCコンパイラに大勝していただろう。
あと、このように毎回実行する余計な処理が4命令もあるので、
ループをアンロールすれば少し速くなると思う。
lea esi, [esi + 2];
lea edi, [edi + 8];
dec ecx;
jnz loop_mp;
>>102 SP6か。それは残念。後でnasmでも使ってみてください。
Pen4だとALUが速くてMMXが遅いからな。
画像処理はメモリのアクセス速度がボトルネックだよな〜
SSEが使えればprefetchがあるんだけどなぁ。
107 :
100 :2006/02/18(土) 10:01:35
いろいろと助言ありがとうございます。参考にしていろいろ試してみます。
>>103 >後でnasmでも使ってみてください。
個人で試す分には思いっきりやってみたいところなのですが、
そこまですると引き継ぎが出来なくなって(略)な事になるので……
108 :
デフォルトの名無しさん :2006/02/18(土) 18:14:08
いまどきアーキテクチャー依存のアクセラレータなど流行らん
109 :
デフォルトの名無しさん :2006/02/18(土) 20:32:13
>>97 ivec.h
fvec.h
dvec.h
をインクルード
>>109 そういったクラスライブラリじゃなくて言語の拡張仕様に
埋め込んで欲しいって言ってんじゃないの?
俺も妄想言語は考えてるよ。つーかみんな一度は考えてるんじゃないかなぁ multivalue< float, 3 > m0( 1.0f, 2.0f, 3.0f), m1( 5.0f, 5.0f, 4.0f), m2; simd foreach( float v0 in m0, float v1 in m1, float r0 in m2) { float t = v0 * v0 + v1 * v1; if( t > 0.9f) r0 = t; else r0 = 0.0f; } 分岐は、通るブロックは全て実行して最後論理積って形になるかなぁ。 誰か作って、C++へのコンバータでいいからさ。
どうみてもivec.h/fvec.h/dvec.hの使い方慣れたほうが楽です F32vec4 m0(1.0f, 2.0f, 3.0f, 0.0f); F32vec4 m1(5.0f, 4.0f, 4.0f, 0.0f); F32vec4 m2 = m0 * m0 + m1 * m1; m2 = select_gt(m2, F32vec4(0.9f, 0.9f, 0.9f, 0.9f), m2, F32vec4(0.0f, 0.0f, 0.0f, 0.0f));
ここが実現してくれるの待ちましょう。どうも税金の無駄遣い臭いのだが。
そういや ・データ読み込み ・同アドレスにデータ書き込み を行った場合、このデータ書き込みの際にmovntiとか使っても全然 早くならないんだけれども、これって対象アドレスに既にデータが入っている 場合、非テンポラル指定はキャッシュ汚染を防ぐためにやるんだから キャッシュに入っていては意味が無いって事だよな?
>100 vcpp5解凍してml.*をコピーすればSSE2命令くらいまで使えたはず、 ってか俺はVC6SP6で使えてる。 もしくは、VC6インスコ→SP5→vcpp5→SP6でもいけた希ガス。
434 名前:・∀・)っ-○●◎- ◆Pu/ODYSSEY 投稿日:2006/01/11(水) 00:05:58 論破されてやがるざまぁwwwwwwwwwwwwwwwwwwwww
>>115 意味ないね。その場合ってロードをプリフェッチすれば
ピーク性能を引き出せるのかな?
119 :
100 :2006/02/20(月) 20:02:21
金曜日にお世話になりました>100 です。 >101 殿のアドバイスを元に、改良版を作成して実験したところ、試行1回あたり 0.01msほど早くなりました(笑 #640×480サイズ、1万回試行の平均。 MMXレジスタ8本全部使って16ピクセル分1ループで処理するサンプルも実験 してみましたが(ループ回数削減を企図)、やはりほとんど変わりませんでした。 処理画像サイズを大きくしても、0.1msほどの違いしか出ないことを考えると、 「メモリ速度がネックになる」という>103、>104 殿の指摘にハマっていそうです。 他の作業指示が飛んできたので、現状でこれ以上の追求は出来なくなって しまいましたが、メモリ速度や最適化の意義などについて深く考える良い機会に なりました。折を見てまたいろいろ試してみたいと思います。 >116 殿 かなりそれは魅力的な手段ですが……引き継いだ後に環境再構築できる人間が(ry
120 :
97 :2006/02/21(火) 12:50:45
>>111 いや言っている。
どちらかというと言語の標準仕様であってもらいたいね。
件の記法が正式採用されたら最適化エンジンは楽チンにベクトル化出来るし
SIMD使えないときでも依存関係の解析が楽になる。
処理が長いときはスレッド化だってイケる。
どれかの言語がこんな感じの機能を実装したら(あるいは約束したら)、
明日にでもその言語に乗り換えるね。
>>119 0.01msか。思ったより効かないな。
prefetchの代替ならmovを使うという手もあるが、この処理の要はmovntqだからな。
後で俺も試してみよう。
Win機でのprefetchはいろいろやったけどあまり効かなかった。 効果てきめんな人居る? 別のCPUでうまいこと使って爆発的に速くなった経験はあるから、 ちゃんとはまれば効果があることは理解してるんだけど失敗続き… VTuneとかでメモリアクセスのパターンとか見れば何とかなるか と評価版を試してみたけど結局うまく行ってない。残念無念
非実用コードで試しても、1割くらい速くなるだけだね。 キャッシュラインは64byteないとほとんど効かないと思う。
PGIスレにぎわってないけど、ホントに性能出るもんかねえ? intelでもオレのケースではまったく効果なかったし(性能クリ ティカルな部分は全部SIMD化している)、iccで最適化 かけた性能はオレのasmコードにぜんぜんのよばねーし。
ハードウェアプリフェッチついてるから、 ソフトウェアプリフェッチの効果薄いのかもね。 メモリアクセスレイテンシ対策にはiccの #pragma unroll(?) は段数変えてみると結構効く場合があるね。
バタフライ演算が華麗に書けないのは痛いな。他のレジスタにコピーして 別に計算、マスクしてから元のレジスタに加算とか、ステップが余計にかかって しょうがない。 二次元DCTをFCTで書いたものと、まともにDCTしたものを比べたら、普通の DCTのほうが幾らか速かったorz 腕が悪い可能性も大だが。 V-Tuneなんつうブルジョアなものは持ってないので、visioでダイヤグラムを 書いて、ペナルティを極力食らわないように組替えてからソースを書きました とさ。手動最適化マンセー。
shuffle命令やSSE3使ってる?
129 :
デフォルトの名無しさん :2006/02/22(水) 10:48:20
SSEすら使ってない。 お客は5、6年位前のスペックでも結構平気で使ってるからな。 SSE3対応の石にせよ、この国ではすでにデスクトップ市場を越えたノート市場で 最近出始めたばかりで、使えないことのほうが多い。 Intel Macあたりが対象なら、あんま考えなくていいけど。 まぁMMXまでは完全に存在を前提に書いたりするがな。 MMX非対応の石はどのみち絶対性能が不足するので切り捨ててる。 つか、SSE2/3って、本当にごく特殊な演算を除けば、MMXの有無程にはパフォーマンスに影響ないんだよな。
>>129 >SSE2/3って、本当にごく特殊な演算を除けば、MMXの有無程にはパフォーマンスに影響ない
同意
MMXでの高性能化に比べてSSE以降はかなりがっかりなのだ。
MMXと同程度に努力したが同じ率での高速化はしなかったよ。
掛け算に無符号が付いたMMX2は最初からやっとけと
ま、あれか。プログラム起動時にCPUの種類を判別して、それぞれに 最適なルーチンを走らせるというのが普通か。
手動最適化はMMXだけ使って SSEはコンパイラに丸投げ そんなシナリオを想定してある感じ
MMXはまぁ当然として、SSEはP3/AthlonXPからだっけ? x86の浮動小数点命令は使いにくいからSSEでの最適化は欠かせないなぁ。 3D Now! の話題が全く無いのは互換性割り切るほど速度出ないからか。 >129 SSE2/3の命令ってmov系と高精度演算命令系以外になんかあんの?
>>133 MendocinoコアCeleronの載ったマシンとか現役で使ってる人が結構いるから
SSEも迂闊に使えないwww
もっとも、うちは基本的に整数演算か倍精度実数演算しか滅多に使わない
人なんで、パックド単精度ってそんなに有り難味が無い。
pmovmskbとかmaskmovqとかもそれなりに便利だけど、わざわざ別々の最適化コード
書いてディスパッチするだけの労力に見合った効果も得にくいんだよな。
> SSE2/3
ホラ、あるじゃないか。MMX/3DNOW!を無理矢理二つくっ付けた様な糞命令群が。
このへんは演算ユニットが128bit化するときのための布石と考えてるが。
てか、64bitになるとMMXもそろそろ要らなくなりそうな雰囲気。
飽和演算とか撹拌処理とかやらなくていいなら汎用ALU使ったほうが速度が出るんだよね。
>>100 のコードと、
>>119 で使われたと思われるコードで測定してみた。@PenM
640*480*16で、43.7msと43.2msくらい。1%程度の違いしかない。
最初からL2ヒットであれば>119が倍近く速いので、やはりメモリネック。
ストアに対してprefetchntaを使うと30.8ms。効いてます(ライトスルーのP4では効かないかも)。
ていうかプリフェッチなんかせずにストアをmovntqにすると18.1ms(これはP4でもOKだと思う)。
単純な処理の割に、MMXが効かずSSE(MMX2)が効くというヤツであった。
>>119 仕事で使っているみたいだから無理だとは思うけど、
>>100 のコードのmovq [edi], mm0;の行を
_asm _emit 0x0f _asm _emit 0xe7 _asm _emit 0x07;//movntq [edi], mm0 のマシン語コード
このように書き換えればmovntqが使えますぜ。
俺の環境だと20.0ms。たった1行書き換えただけで倍以上速くなるのは気持ちいい♪
>>115 prefetchntaが最速だった。
ロードなしのmovntや、ストアなしのprefetchロード、というならもっと速いが、
ロードとストアを両立させようとすると、prefetchntaという結論になる。
>>134 >Mendocinoコア
めんどっちーの、と読むのか?
略してマンコア
138 :
デフォルトの名無しさん :2006/02/23(木) 20:53:08
>135 殿 アドバイスありがとうございます。 実験してみましたところ、おおよそ速度が4倍にアップしました。 こりゃすげえ! と思ったのですが、上長には却下されました。 『だれもわからねぇYo!』だそうで。 さすがにMMX2まで扱おうとすると、VC6ではやりづらいですね。 上長の上の人に結果まとめてレポしてみて、環境更新するよう具申してみることにします。 ちなみに、こちらの環境で一番速かったのは、>101殿のアドバイス を受けたもの(>119報告のもの)の改造版でした。 void test4( void *dst, const void *src, int size ) { int size2 = size >> 2; if(size2 != 0){ __asm{ mov edi, dst; mov esi, src; mov ecx, size2; loop_mp: movd mm0, [esi]; punpcklbw mm0, mm0; movq mm1, mm0; punpcklbw mm0, mm0; punpckhbw mm1, mm1; _asm _emit 0x0f _asm _emit 0xe7 _asm _emit 0x07; _asm _emit 0x0f _asm _emit 0xe7 _asm _emit 0x4f _asm _emit 0x08; add esi, 4; add edi, 16; sub ecx, 1; jnz loop_mp; emms; }} }
MMX2って何?SSEで入れられた整数演算?
もともとはSSEの旧い仮称だった気が。 今はへるみ氏あたりが初代AthlonでサポートされたEnhanced 3DNOW!とで 共通で使える拡張命令(要するにSSEのMMX整数演算拡張)を総称して そう言ってるような。 案外午後な人書き込んでるかもしれんね。
浮動小数点形式にすればバタフライ演算は可能になるが、そのかわり 一度に演算できるデータは少なくなる。 16bit整数でバタフライ演算すれば同時に処理できるデータは8点に増えるが、 同じレジスタ内に0以上1未満の整数値(シフト処理したもの)と1以上の 整数値が混在する場合は、バタフライ演算で同時に演算できない。 該当するデータはいったん別のレジスタで処理しなければ成らないため ステップ数が増える。 精度を保って処理したいなら単精度小数点などで処理するが、リアルタイム 性能を追求するなら整数で処理するしかないかな、と。 まぁ、どうせインテルは本当に便利な命令は用意しない方針のようなので。
ソフトウェアパイプライニングとか 手でやってる?コンパイラまかせ? x64だとレジスタ数も違うし、そもそも CPUごとにレイテンシ等変わって面倒だよね?
Athlon系はレイテンシが長いからL/S頻度上げてでも並列化汁 PenMは全般にレイテンシ短いから程々でヨシ NetBurstはパイプラインの長さの分OoOが強力だからあんまり何も考えないほうが かえって良かったりするかも。 という風に把握している
144 :
デフォルトの名無しさん :2006/02/24(金) 08:45:35
っ[ドトニート]
ん、MMX2ってAMDがつけた3D-Now!の前の名称だったのでは? MMXを機能拡張したCPUをAMDが出したとき、インテルが「MMXはうちの登録商標 だから使うな」とAMDを訴え、AMDは「マルチメディアエクステンションなんて 平凡な名称だ」と反発していたような。 違ったらスマソ
確かにクソ平凡だよな
俺はMMX2ってSSEの中でMMXレジスタを使うものをIntelが呼んでいたんだと 思っていたが、何か違うみたいね。ぐぐっても少ないし。
>>146 古いソースを漁ってみるに、MMX2はSSEがまだ世に出る前の仮称。
SSE自体もKatmaiが出始めた頃はiSSE(インターネットストリーミングSIMD拡張)と
呼んでたり。
AMDその他CPUメーカーがMMXを使うこと自体にIntelが提訴したのでは。
Intel側の主張は棄却で和解したはず。
すんまそん、技術自体ではなく名称ですね。 サポートされた拡張命令セットが同一であっても、あくまでカタログ上は Enhanced 3DNOW!、3DNOW! Professionalなどと称し、SSE、SSE2という商標名は 使ってませんな。
3DNow!はSSE+αなんだからSSEと名乗るのは変じゃないか
まぁそうなんだけどEnhanced→ProfessionalはIntelが先行して行ったXMMレジスタ周りの 拡張命令のサポートで、AMD独自の拡張命令の追加は無い やっぱり商標権のトラブル回避の為でしょうな
153 :
デフォルトの名無しさん :2006/04/25(火) 20:19:34
MMXに命令が追加されたときにユーザーが俗にMMX2と読んだだけなんじゃなかったkk手
0x8E574343みたいなHexのデータが延々と続いたデータの 中から、特定のhex列を見つけたいと思ったらアルゴリズムは 別の領域として高速化するのにSSEとかは使えそう? もし使えそうだったら簡単なサンプル示していただけないでしょうか
キャッシュに納まるサイズのデータの中を何度も検索するんじゃなければ 普通にCで書いてもMMX使っても大差ないような気がする。 巨大データ(and 古いCPU)ならむしろ prefetch の有無で変わってくる。
えーとCPUはOpteron850とかXeon 3.6Ghz当たりを64コアから512コアぐらいを 想定しています。データは1データあたり1000バイト程度それが秒間900MB/sec 転送されてきますそれをリアルタイムで処理しないといけません。そうするとCで 書いても大差ないですか。
>154 その程度のサンプルも書けないレベルなら諦めろ。 結局メンテナンス出来ずに回りに迷惑かけるだけだ。 >156みたいな用途ならおとなしくCで書いとけ。
900MB/sのネットワークがなんなのか気になる
SSEはレジスタが広いけど、
汎用レジスタで最初の4byte一致したら続きを調べるってすれば実質変わらんしなあ。
「特定のhex列」の登場頻度が高いなら別だけど。
あ、でもこれもSSEで並列にやればいいんだ。hexは1/2バイトなのも考えて。
「特定のhex列」のバイト数は?
2バイト単位くらいで比較して、4bitシフトしてまた比較。
一致するものがあったらそこを普通に調べる。
これなら数倍比較コストが減るんじゃないか。
#まあ、メモリ帯域ネックから高速化はしないと思うよ。
あとはキャッシュラインをまたぐときに気をつけること。ここもうまくやればSSEが有効か?
ていうかCで書いて速度が足りないから
>>154 で質問したんじゃないよね?
普通にCで十分な速度だと思うよ。
スペック見る限り結構な規模のプロジェクトだし、 そんなプロジェクトで汎用性が無くメンテナンス性の悪いアセンブラを使おうってのが間違ってる。 しかも知識も無いときたら周りに迷惑かけるに決まってる。 や め と け。
昔似たようなことやったけれどあんまり意味が無かった記憶がある。
いまやSSEもAltivecもCで書く時代
みんな言ってることは正しいと思うけど、 このスレ的にはアセンブラでSIMDを使い無駄な最適化をするべきじゃないか?
>無駄な最適化 www なんかわかるw
154タンはいなくなってしまったか。。
いやいるし勉強してるんだけど、いまいちよくわからない もう少し修行してきます
>>166 いたか。いつでもいいので修行したら報告ヨロ。
とりあえず、gasとnasmどっちでインラインすればいいんだろう gccだと一択なのかな?
SIMDの資料ってみなさんはどこから取得してるのでしょうか?
ていうか検索アルゴリズムってどう最適化しても 結局メモリ帯域で頭打ちになるっしょ
172 :
・∀・)っ-○◎● ◆toBASh.... :2006/05/05(金) 19:52:44
黙れキチガイ
組み込み関数を利用してSSEプログラミング勉強しようと頑張ってみたのですが 以下のようなクラスを用意して、一度に16バイトずつuchar型のデータを判別しようと しましたが、このchar型のデータをSSEで計算するにはどうしたらいいのでしょうか class CHARVector { union { __m128 vec; struct { unsigned char c1, c2, c3, c4; unsigned char c5, c6, c7, c8; unsigned char c9, c10, c11, c12; unsigned char c13, c14, c15, c16; }; }; // ... };
175 :
・∀・)っ-○◎● ◆toBASh.... :2006/05/19(金) 01:26:16
>>174 __m128じゃなくて__m128i使いなよ。ただしSSEじゃなくてSSE「2」ね。
SSEまでなら単精度浮動小数×4までしかサポートされない。
C++ラッパー1から作るくらいなら最初から用意してある物使ったほうがいい。
#include <dvec.h>
VC++かICCならこれで Iu8Vec16 っていうクラスが使えるはず
すいません環境書くの忘れたのですが、 RedhatEL4 gccで作成しています。gccだとdvec.hが使えないと 聞いて悩んでいました。
177 :
・∀・)っ-○◎● ◆toBASh.... :2006/05/19(金) 01:45:07
>>177 うーんサンプルコードってあるのでしょうか?
179 :
デフォルトの名無しさん :2006/06/13(火) 01:35:19
すみません、ANDPDとANDPSって何か違いがあるんでしょうか? どっちもxmmレジスタ同士のandを取るだけのような……
マシン語コードが違う。命令長は同じ。 動作も同じだと思う。 ニーモニックが2つあるのはいいとして、 なぜマシン語コードも違うのか謎ですな。
ANDPSは、SSEまでカバーしていれば使える。 建前上、パックド単精度実数が操作対象。 ANDPDは、SSE2をカバーしていないと使えない。 建前上、パックド倍精度実数が操作対象。
機械語は敷居が高すぎて手を出せないので、C言語だけで3DNOW!やSSE対応の プログラムは作れないものでしょうか。
MMXやSSE命令をラッピングした組み込み関数が用意されている開発環境があるよ
なんでもそうだけど、知らないと食わず嫌いで難しそうに思うけど やってみるとそうでもないもんだよ。
185 :
デフォルトの名無しさん :2006/07/05(水) 13:03:54
>>183 つか、x64やIL向けだとインラインアセンブラ無効だからそれ使うしかない
186 :
デフォルトの名無しさん :2006/07/05(水) 13:08:38
実際問題mmintrin系組込み関数は構造化設計ができるし、命令スケジューリングの最適化も阻害しないから 結構便利なんだよな
命令スケジューリングっていうか、VC++ の場合inline 使うと 前後でも最適化が一切行われないよね。
>>187 される。
まさかとは思うがコンパイルオプションミスったり、
デバッグモードで確認なんかしてないよな?
ホントダ・・・誰かに騙されていた!! 簡単に確認できるのに確認しない漏れって・・・orz
190 :
デフォルトの名無しさん :2006/07/06(木) 11:38:10
最適化されないのはインラインアセンブラ(__asmステートメント)の前後や中身。 inlineとか__inlineキーワードはむしろグローバルな最適化(高速化)のためのもの
>>190 漏れもそう思ってだんだけど、Visual Studio 2005 の C++ で実験してみると
同じ関数内の __asm 後のコードもきっちり最適化されてるわけですよこれが・・・
char a[100]; for (int i = 0; i < 100; i++) a[i] = i; int sum = 0; for (int i = 0; i < 100; i++) sum += a[i];
で、全てC++で書いても最初の初期化のトコを __asm で書いても、後者の加算のループは
5つずつ加算する20回のループに展開されますた。
インラインアセンブラの部分まで勝手に最適化されたら神認定なんだが。
インラインアセンブラの部分を勝手に最適化しやがったらキレるだろ普通。 アセンブラで記述しなきゃいけない部分は何らかの理由があって わざわざそういうコードにしてるものもあるのに、 それを別の命令に置き換えられたらブチギレですよ。
>>191 関数の前半と後半を__asm{nop}でぶった切ったら最適かもぶった切られたよ。
「最適化もぶった切られた」ってのはどういう意味ですか? 後半が素直な100回ループになっちゃったってこと?
>>194 コンパイラによって結果は異なってあたりまえだろ。
漏れのとこの VC++ 2005 では __asm{ nop}; 入れてもnpad 1 が間に入るだけで
全く変らないコードが生成された。
>>195 __asmをまたいだ最適化はしない、ということかな?
198 :
196 :2006/07/07(金) 13:16:40
>>197 そういうことじゃないんじゃないか?漏れのトコでは前述の通り npad 1 の有無だけ。
そもそも__asm 入れなくても「またいだ最適化」みたいなものは無かったし。
単に
>>194 の使ってるコンパイラが__asm 入れると最適化しなくなる旧いVCとか
なんじゃまるまいか?
>>195 forループではないんだが、FPUレジスタの使い方に無駄が出た。
ある関数の最初の方で別のライブラリの関数にfloatの変数渡して、
いくつか別の浮動小数点の処理した後で変更なしで再びその変数を使うんだが、
この間にnop入れるだけでもう一回メモリから読み出すようになった。
>>196 すまんがforループなんて単純な部分ではなく、しかもVC8での話なんだ。
インラインアセンブラ挟んで最適化を期待する方がおかしい気がしますが。 しかも複雑な部分なら尚の事。
202 :
200 :2006/07/07(金) 21:27:22
>>201 アンカーがないから俺へのレスってことでOKなのか?
おれは__asmブロックで最適化が阻害されるのは当然だと主張してるのであって
最適化されねーぞなんでだヴォケと言ってるわけじゃないんだが。
>>200 その話の真偽はおいといて、
>>191 >>194 を読んでそんな風に理解できるかというと、
それはちょっと無理じゃないか。
漏れは 191 の関数の前半と後半という風に読んじゃたよ。
想像力が無いからかもしれないけど。
>202 当たり前の結果にムキになってっから、何か不満でもあるのかと思った。
>>81 古い話だけど今のICCには_mm_cast*という命令があってこれでキャストできることに気がついた。
VCLにはない。GCCは普通に(__m128)とかでキャストできる。
206 :
・∀・)っ-○◎●新世紀ダンゴリオン ◆DanGorION6 :2006/07/08(土) 17:53:16
浮動小数の2倍とか1/2倍とかやるのに指数部を直接整数として足し算引き算すると確かに速いんだよな AMDが来年予定してる新リビジョン(K8L)でXMMレジスタの下位・上位QWORDと汎用レジスタ命令の値を 相互に交換する追加されるみたいだけど、これってIntelも採用するかのう? 別のニーモニック割り当てるんだろうな。
207 :
・∀・)っ-○◎●新世紀ダンゴリオン ◆DanGorION6 :2006/07/08(土) 17:54:25
×汎用レジスタ命令 ○汎用レジスタ
208 :
182 :2006/07/13(木) 16:03:54
みなさん、どうもありがとうございました。 3DnowやSSEを使えるようになるのを目標にして、機械語を勉強するのに 良い参考書がありましたら、教えていただけませんか。 NWSAというのを見つけて、解説を読んでいますが未知の言葉が山盛りです。
SIMDが載ってる本 x86アセンブラ入門 アセンブラ画像処理プログラミング 載ってない本 独習アセンブラ アセンブリ言語の教科書 糞級言語プログラマのためのアセンブラ入門
絶対に買ってはいけない本 いまどきのアセンブリ言語 いまどきのアセンブリ言語の教科書
「IA-32 インテル アーキテクチャ・ソフトウェア・デベロッパーズ・マニュアル」 を読んでSSEが難しいようだったら多分それを触る前に覚えることがまだまだある。
>>212 そうかな。俺はよくわかんないうちから
MMXでガンガンコード作って覚えたけど。
あのマニュアルを読むのは、ある程度
SSEを使えるようになってからでないときついだろう。
>>213 212ではないが、あれ読めないって事は結局x86の構造理解出来てないって事だと思うが。
通常命令での効率的な組み方を勉強する方が先じゃね?
Core2に搭載されるISSE4っていったいなんだろう。
CASL IIやれば十分だよな
単純な画像変換とかをMMX化SSE化して デバッガにかけながら読むとテラわかりやすいお。
だれか Core2 に搭載される(た) SSE4 のマニュアルを ダウンロードできるとこ知らない? www.intel.com とか探しても全然見当たらない。 まだ非公開かな? それにしてはベンチマークが対応しているのが不思議...。
糞団子のページに書いてあるよwwwwwwwwww
あれはニーモニックから推測したものでしょ。 TMPGEncだかも対応したよな。 開発者向けには公開してあるってことか?
TMPGEncはIntelが金出して最適化してたはず。
なるほど。抜け目ないね。 TMPGEncはベンチとしても一般的だからな。
推測っていうか、既にICC9.1でこっそり対応してる。組み込み関数も既に用意されてる。 団子のページ引用率高すぎ
C言語のプログラムの途中たった一行だけ、計算式をインラインアセンブラで MMXやSSE、3DNOWに対応させるというのは可能ですか。
たった一行だけのためにemmsを使うのはアフォ
最低でもループの一番内側丸ごと、じゃないかな。 emmsもdろうけど、SIMDはデータをレジスタに乗っ けるところが結構食うからね。
アンロールしまくれ SSE2の整数命令ってSSE2非対応CPUはMMXの相当命令として解釈されるから うまく組めばパスの分岐必要なし
gccでintrinsic function使ってSSE2,3の処理書きたいんですけど 3年ぐらい前に書くとアライメント指定しても4byteでまとめられたりして まともに使えなかった記憶があるんだけど今はどうなんですかね?
_mm_malloc()かunion共用体使う
SSE4の仕様解析出たな
>>226 SIMDのデータ転送のレイテンシが半端なくでかいのはPen4くらい
AthlonやPenM, Core系は整数と大して変わらない
ようするにネトバは糞って事?
ネトバカッコイイってほざいてたのは雑音だけ。 SIMDとSIMMを間違えるのも雑音だけ。
たるさん…
psign*とpalignr間違えてましたすいません。
SSE4って命令部3バイトだからあんまり使えない気が。
XMMレジスタでREXプリフィックス付けたら命令長最低6バイトになる
>>228 ヒープ上に16バイトくらい多めに確保して、返ってきたアドレスに15足して~15でマスク。
Windowsだと、SSEがまともに使えるようになったのがVC7からだと記憶してる。
SSE4のレイテンシやスループットの数字って出てる?
非公式ながら、x86の〜スレにある。 正式名称はSupplimental-SSE3(SSSE3)になったらしい。 あと、まるも製作所の中の人が色々と考察してた
へえ、SSE4じゃなくてSSE3に追加するという形か。
長いからSSE4かTNIでいいよ
追加って話ならSSSEよりSSE3sのが理にかなってわかりやすいなぁ…
Enhanced 3D Now! みたいなものだろう。 ただ、次に命令を追加するときに「SSE4」とされるとややこしいな。
次はSSSSE3だな
スプラッシュスターSSE3
Streaming SIMD Extensions eXtendedにするべきだと思うんだが
今後、SSE4はSSE4と呼べばいいが、 SSE3+SSSE3を総称した呼び名はできるのかな。 命令が普及した後で、SSE3と言ったときに、 SSSE3が含まれるかどうかが不明確になりそう。
総称がSSE3だろ プレスコは要らない子
そっか。じゃあ、Prescottと最近のK8だけ仲間外れだ。 あれ、Cyrixの系統のやつも載せてたっけ。 今度はSSE3(総称)の中のSSSE3に含まれない命令の 呼び名がないと不便になるなあ。
SSSSSEE33
SSE3-FP
SSE3-Classical
SSE3ESS
PNIとTNI(MNI)でいいじゃん。 PenrynもPだから困る。
>>251 なるほど。
Penryn New Instructionsの略称はどうなるのかね。
まあSSE4と呼べばいいだろう。
ところでこのスレも2年以上になるのだが、
今こういうスレを立てるとしたら、3D Now!の名前は入るだろうか。
まあ、2004年と言えばとっくに3D Now!は下火だったが。
もう2年になるのか・・・。
少し遅れて来て
>>25 が取れなかったことを
昨日のように思い出す。
>>255 こ、更新日時が2004/12/12 10:07!!
俺は特に見たかったわけではないが、
>>255 はある意味で神。
よかったな、
>>32 !
これから、64bitのWindowsが普及してくる(使えるレジスタ倍増)のと、 Core2やK8LでSSE命令のレイテンシは据え置きでスループットが倍になること、 これらによってSSEの使い方がかなり変わってくるだろう。
急にSIMDとかインラインアセンブラ使いたくなってやってみたんだけど、 トイプログラムで A: SIMD化+とことんオプション最適化 B: とことんオプション最適化 C: SIMD化 D: 軽くオプション最適化 E: ベタ書き で A:B:C:D:E = 10:15:30:35:60 #速度比 と、実は結構コンパイラオプションのチューニングだけで いけてしまうことがわかってコンパイラスゴスと思ってしまった。 A:Bでも10:15位の速度比があるのでSSEとか効いてはいるんだけど、 最初はC:Dで止まってて「あんま変わんないなぁ」とか思ってたら B:Cで15:30とオプションいじるだけで下手なSIMD化を抜いてしまって 驚いた。よほど性能が必要なケース以外は下手に拡張命令使うより コンパイラお任せで十二分にいい仕事してくれるのな。 自分は拡張命令覚えるよりコンパイラオプション覚えたほうがいい レベルなのだと痛感しますた・・・
処理内容に依存するからなあ。 どんなの? SIMD化というのはインラインアセンブラ? コンパイラに頼るなら組み込み関数という手も。 インラインアセンブラをまたいでは最適化が効かない。 最近はCPUが賢いというのも コンパイラ有利な要因かも。
>259 SIMDで最適化するならデータの配置も最適化しないと意味無いぽ。 てかコンパイラ、サンプルコード、計測方法、コアの情報も無く比だけ提示されてもな、って感じ。
正直、そのデータ配置の最適化ってのがどういうもんなのかよくわかんね・・・ セオリーとかあるの?
インテルのマニュアルにSoAとかAoSとかについて書いてある。
何にせよ、どんな処理を高速化したいのか 書いてくれないと話が進まない。
>>260 いや、トイプログラムって書いてる通り、1M個くらいのfloat列を
2つ乗算するだけのコード。インラインアセンブラもやったこと
なかったので、最初はインラインアセンブラで書き始めて、途中で
Intel/MS/GNUが全部同じAPIで叩かせてくれると気づいて書き直した。
これまでやったことがなかったので経験のためやってみただけなので、
あまり真剣に取らないで・・・スマソ。
でもコンパイラオプションだけで考えていた以上に性能が接近すると
知ったのは収穫でした。問題の部分に使うクロック数で非SIMDは3倍
程度はかかるかと思ってたから。
>>265 そういうのをトイプログラムというのか。
今のCPUだと、floatならSIMDの方が速いと思うが、
float*1M個*2つ=8MBなので、L2キャッシュに乗らず、
単にメモリがネックになってるだけと思われる。
非SIMDでfloatの乗算をするのに、うまく最適化すれば
Athlon系なら1クロック、Pentium系なら2クロックでできる。
それに対しメモリ帯域は1〜2byte/clkだから、
2つのfloatをロードし結果をストアするのに12byteのアクセスを
するのに全然帯域が足りてない。
つまり、ここで必要なのはSIMDでなくプリフェッチ。
>>259 のどのコードも、FP演算ユニットは遊んでいたと思われる。
もっとも、SIMDのロードやストアはアクセスの単位が大きいので、
メモリアクセスが効率化されて若干速くなる。
AとBの差はそれだろう。
結果の格納を別の配列にしてるんならmovntpsが有効なのでつ x87からライトスルー命令は使えないし、やっぱりSSEまんせー
>>266 いやそれがですね、-fprefetch-loop-arrays とかいうオプションが
あってまさにそれやってくれてたんですよ。
わざわざ拡張命令使わなくても限定的ながら自動ベクトルかとかも
してるそうで、もうコンパイラ様々というか。
>>267 あ、それを忘れてた。
>>268 すごいなコンパイラ。
すると、インラインアセンブラを使うと最適化が効かないから
プリフェッチもしてくれないわけで、それでAがBに勝ったの?
コンパイラの吐いたプリフェッチコードキボンヌ。
そもそも機械的な最適化に負けるコード吐いてる次点でSIMDがどうこう言う資格無い。 時々勘違いしてる奴がいるが、アセンブラ化すれば速くなるわけじゃない。 コンパイラで出来ないことをアセンブラで最適化するから速くなる。 MMX/SSE命令並べただけで速くなるならコンパイラだってそうするだろうよ。
>>270 コンパイラに負けるから勉強して
SIMDを使えるように頑張るんじゃないか。
うん、勉強頑張るのはいいよな。 「コンパイラの最適化で十分」とか結論付けるのは良くないよね。
VC8で64bitコードにインラインアセンブラを使えないのが腹立たしい。 MASMだと煩雑だしプリプロセッサも無い。 組み込み関数じゃ思った通りの命令を生成しない。
COFF形式でコード吐きだせば別にアセンブラは何だっておkだよ。 むしろx64対応のアセンブラそのものが少ないのが問題。 x64でプログラミングやるならVC++Std + PSDK + ICCが一番コストパフォーマンスいいと思う。
yasm使ったことある人いる?
インラインうぜーよ モジュール分けろやボケが
277 :
デフォルトの名無しさん :2007/02/18(日) 10:10:27
裏切派遣って知ってる? 元々は正社員だったのに取引先にフリーのほうが稼げるとか騙されて派遣やってるバカのことw 前の会社を裏切り、結局派遣先からも騙されてる。 そもそも信頼されてるなら直接契約するか正社員にするはずだが、派遣会社経由って舐められ杉 自分でも騙され裏切れられてることは薄々わかってるから派遣問題の話が出るとウッキー!って逆ギレw
そんなサイトよか光成さんの方がよい
むしろこのスレで知らない人が居るのに驚いた訳だが
禿同
今更ながら MMX を使用した MMX_MemCpy() を作ってみたが普通の memcpy() と10%も速度が変わらなくて萎えた…
FSBで律速されるからね。 キャッシュ内で使う場合は十分意味ある。
>>286 の言う通りメモリの速度に依存する。
それに64byteとか128byteごとにキャッシュされるんだから
4byteずつコピーしようが8byteずつコピーしようが殆ど同じ。
重要なのはプリフェッチ。
L1のサイズをきちんと考慮してプリフェッチしてからmemcpy()を繰り返してもいけたりして。
288 :
285 :2007/03/14(水) 07:59:02
そうなのか… 8Byte境界なら MM7 レジスタまで使用して64Byte転送するとかやってみたんだが同じなのか。orz
数%でも高速化されるならそれは凄い事だと思うよ
後は用途によってノンテンポラル関連を使うとかだよな。
291 :
285 :2007/03/15(木) 23:32:55
>>289 最初はそう思おうとしたが、さらに速いマシンで実行したら効果がさらに薄くなったんだよつД`
1Gコピーしても50msも変わんねぇ
そんな大容量のコピーするからこそかわらんのですよ キャッシュの中でうまく捏ね回すのがSIMDプログラミングの掟
正直単純なメモリ転送を最適化する暇があるなら、転送中ヒマをもてあましてる演算器の活用方法でも考えたほうが。
32bitのDIB(R8G8B8A8)を24bitのDIB(R8G8B8)にアルファブレンドする関数を書いているのですが、 Cでテーブルを使って実装すると、テーブルへのアクセスがボトルネックとなって、 他の処理と比べて重くなってしまいます(テーブルは256x512x4で、L2にも入らない)。 そこでMMXを使ってみようと考えたのですが、 MMX命令を用いた計算方法そのものは分かるものの、 ピクセル単位の異なる二つの画像を、上手くMMXレジスタに配置する方法が分かりません。 どなたかご教授下さいませんか。 #どちらのDIBも、横幅が8の倍数であることは保障されています。
mov ecx, pixelcnt mov esi, DIB32 mov edi, DIB24 label: mov mm0, esi mov mm1, edi --なんか処理-- add esi, 4 add edi, 3 loop label 後は最初か最後にediからの読み込みに1Byte前後して読んでシフトする処理が必要になるけど、 ループの外で処理すればいいし、テーブル参照するよりゃ速いんじゃね?
>>295 どうもありがとうございます。
シフト処理を入れたら上手く配置できて、
二倍近く速度が出るようになりました。
>295 どーでもいいけど、 mov mm0, [esi] mov mm1, [edi] じゃね?
っていうかmovdじゃね
movq な。
あ、この場合movqでなくてmovdになるか…。
つまり団子は普通に名無しで潜伏してる
イミフ
上下で都合2マソ取ろうっての?ボッタクリ過ぎだろ。 x86アセンブラ入門+IntelのPDFで十分。
>>303 要らん
操作画面の横でPDF表示する為のサブディスプレイを2万で買ったほうが有意義
ひでぇ商売だ
308 :
デフォルトの名無しさん :2007/05/27(日) 17:41:16
mmxって廃止なの? 代わりに何をつかえばいいの?
>>303 不要。
最近のコンパイラは、SSEを自動的に使ってくれる。
むしろ、その最適化にやさしいコードを書いた方がよい。
手動で最適化したところで、大抵数パーセントも上がらない。
SIMD Intrinsicsの解説やってる実践的な本のほうが欲しいな。 それもIntelで十分か。 どうせならAltiVecとかCellのSPUとかも扱って移植性とパフォーマンスを両立する方法とかね。
>>310 Intrinsicsの解説自体はコンパイラのドキュメント読めば十分理解できるだろ。
むしろ実践的なアルゴリズムをいかにSIMDに落とし込むかという話のほうが読み応えないか?
>>309 アセンブラでSSE使うことが不要というのは言いすぎだと思う。
まあ、結果としてこの本が不要という結論にはなるだろうが。
>>310 移植とかは、COINSにお任せしておけば良いのでは
金融SE、プログラマにこの辺やOpenMPのHPC系技術をおぼえてほしいんだがな。 誰もわからんからユーザーの俺がプログラミング。どういうこっちゃ。
金融で、そんなにシングルスレッド性能がいるの??
金融の一部の分野は大量データの高速計算や 複雑な計算を瞬時に行う必要がある。
へー、どんな計算?
>>316 こういう奴ってさも物事を大げさに書きたがるが、具体的な例や数字は
一つも書かないから結局何を言っているのかさっぱりわからないんだよな。
>>318 こういう想像力の無い奴に物事を説明するのって疲れるんだよな
想像力……www
>>318 デリバのプライシングとか、ALMでのVaR計算とかなんだが詳しく書いても
多分分らんと思うが。
知らないことを想像しろと言われても、ヒントもなしでは結構難しいと思うのだが。
リロードしてなかったorz
>321 それは具体的な「業務内容」であって、具体的な「例」でも「数字」でも無いと思うんだ。 ここが金融系の板ならそれで通じるかもしれんが、ここはム板だから。 例えば必要精度何桁でどんな数式を秒間何万件処理する必要があるとか、そういうこと。 専門用語でお茶を濁す事は具体例では無い。
>>324 たとえば百万件のデータから求める解を得るためにニュートン法等を数種類、複数回駆使ししたり
モンテカルロシミューレーションで数十万回の試行を行ったりといったこと。
これらはスレッド単位の高速化とマルチスレッドでの高速化により絶大な効果が得られる。
しかし高速化の技術を知るエンジニアは極めて少ないのが実情。
ってとこ。
モンテカルロ法でSIMD使って絶大な効果ってどんだけ単純なシミューレションだよ。 マルチコア、マルチCPU環境等でマルチスレッドなら同意できるが、 中途半端にSIMD使っても結局速くなった気がするだけ。 がちがちにコーディングする暇があるなら速くなるかもしれないけど そんなことで工数がホイホイ増えるくらいなら計算機にお金使ったほうがマシ。
>>326 高速化するために数学的手法を駆使したMCなんだが
MCがすべて単純な繰り返しと思っているレベルの頭脳では話にならん。
>327 お前プログラマじゃないだろ? 具体例の無い説明といい、「xxを駆使」とかいかにも営業が使いそうな言い回しといい、胡散臭すぎる。
>>328 流れを読め。
オレ=
>>314 これからこの話題につながってるんだが。
また別にお前に依頼してる訳ではないから具体的に書く必要性もない。
以下、「お前こそ」禁止。
うーむ、よくみりゃ誤字ってたな。
>>327 MCが単純って書いた覚えはないよ。
金融工学の問題ってSIMDがクリティカルに利いてくるような
単純な代数計算なのかって話。
たとえばExceで用意されているNormdistといった確率分布関数のようなものは 商用ライブラリーを購入する手があるが、処理スピードと精度のトレードオフの調整が利かない。 これをCで組むと四則演算+EXPの多用となる。普通にプログラミングするとかなり遅いがSIMDを使うと大幅に 高速化する。SIMDにEXPがあると良いのだが。
その辺はニュートン法使ったりテーラー展開したり。 Intelが数学用ライブラリ出してなかった? x87のアレはどうせマクロ命令なので。 ちなみにdivpsとかで得られる商は近似値で精度低い。
標準関数よりニュートンのほうが早いってことあるのか? ニュートンは方程式を解くのに多用するが初期値問題があるしな。 MKLのEXPは使い方によるだろうが、メモリにデータを貯める必要があるときは高速だろうが そうでないとメモリアクセスの遅さがネックになってあまり役立たない。
SIMDで組み直せば標準関数のスループット越えることなんてざらにあるよ。 あくまでSIMD使うからこそ意味があるんだけど。
へ-そうなんだ。 とすれば試してみる価値あるな。 expのニュートンは簡単そうだし。。。 初期値どうするかな
金融の問題って収束が遅いモンテカルロでどうにかなるのか。
使わないですめばそれにこしたことはない。 解析的に求める方法がなければモンテカルロを使うしかない。 という理由で使われる。
結局金融には直接関係ない部分の話になっちゃったね。
>>335 よく考えたら f(x)=exp(x)で f'(x)=exp(x)だからexpをニュートンで求めるのは無理だな。
テーラー展開でやってみたんだが
・テーラー展開式 exp(x)=肺^n/n!
・階乗部分をすべて初期値設定
0!:n0=1
1!:n1=1
2!:n2=2
・・・
x:入力値
expsse:求める値
x=_mm_mul_pd(x,x);
expsse=_mm_add_pd((expsse, _mm_div_pd(x, n0));
x=_mm_mul_pd(x,x);
expsse=_mm_add_pd((expsse, _mm_div_pd(x, n1));
x=_mm_mul_pd(x,x);
expsse=_mm_add_pd((expsse, _mm_div_pd(x, n2));
・・・
こんな感じ。for分使わずn=20までやって精度9桁くらいだったかな。
しかし処理時間は非常に遅かった。
時間がなかったのであまり詳しく調べなかったがコーディングに問題あるかな?
Visual C++ 2005 で ssse3 の intrinsics が使えるようだ
いつのまにSSSE3まで使えるようになったのか インラインアセンブラのニーモニックは使えるが
>342 お前が>333でネタ振ったんだから責任もって>340のフォローしろや
レイテンシのチェインがある mulpd→divpd→addpd 対象データが複数あるなら複数インターリーブするとスループットが稼げます。
>>344 その理論で行けばSPEのスカラも多くはスループット1クロックで処理出来るんだがな。
つーかx86にその理論を適用するにはレジスタが足(ry
レジスタリネーム
XORでゼロクリアしたり(Core 2からSIMDレジスタにも適用) データ移動(部分データ移動は不可)するとレジスタリネームのヒントになる SIMDレジスタは内部的に80程度はあるからそこそこいけるんでない? Cellの演算ユニットはIntelアーキのそれの倍のレイテンシがかかる。 SPEのスカラが性能でないのは、そもそもベクタ化すら出来ないデータを 並列処理でレイテンシ隠蔽するには限界があるから。
演算器が先にストールする。
連投失礼。 レジスタリネームとかって言ってる人のコードの書き方に興味がある。 よっぽどコンパクトな演算じゃない限り演算結果をレジスタから追い出さなきゃいけないと思うんだが。
問題は十分な精度が得られないことだと思う 速度を上げることはそんなに難しくない 定数除算を逆数との乗算に置き換える ↓ a4*x^4 +a3*x^3 +a2*x^2 +a1*x + a0 ↓ (((a4*x+a3)*x+a2)*x+a1)*x+a0 ↓ tmp=a[N] for(i=N-1;i>=0;i--) tmp=tmp*x+a[i] ↓ (初期化部分は省略) LOOP: mulpd xmm4, xmm0 mulpd xmm5, xmm1 mulpd xmm6, xmm2 mulpd xmm7, xmm3 addpd xmm4, [esi] addpd xmm5, [esi] addpd xmm6, [esi] addpd xmm7, [esi] add esi, 16 sub ecx, 1 jnz LOOP
いや除算は近似値命令だから乗算に置き換えるだけである程度 精度確保できるんじゃないの? Intelはx87倍精度は内部的に80ビット精度に展開して処理してるけど SSEは精度度外視してたような。 精度が必要ならx87のほうがいいかもしれない
近似値なのはrcpps,rsqrtps命令で、 divpsは近似値じゃないんじゃない?
いや近似値。内部的に逆数近似値と乗算してるだけ。
ちなみに本物の除算は何十クロックもかかりますから。
>>353 そのソースは?
rcppsのレイテンシとmulpsのレイテンシを足しても
divpsのレイテンシよりずっと短いよ。
インテルの命令セットマニュアルには
rcpps,rsqrtpsの説明には近似値であると明記してあるけど、
divpsには近似値なんて書いてないよ。
x87を比較対象にしてるでしょ。 そら80bitなら何十クロックもかかるわな。
>>350 スマン、教えてほしい
(アセンブラは苦手なだが)多項式近似のパタンは和算→乗算の繰り返しでやるしかないという認識なのだが
乗算を先に4つやって、あとから和算4つ行うって計算は可能なのか?
>>344 > 対象データが複数あるなら複数インターリーブするとスループットが稼げます。
>>355 すまんそうだったかも。
ただ仮数部全部厳密に求めるほど精度なかったと思う
>>360 別物。テーラー展開とチェビシェフ系の違い。
363 :
350 :2007/06/06(水) 01:01:20
364 :
340 :2007/06/06(水) 19:11:56
>>344 回答ありがとう。
俺の知識ではいま一つ分らんが命令の並び順に工夫がいるということと
他のデータも同時に処理できたら同時に行うということかな。
>>363 確かに最初がまちがっとる。記述ミスなのできにしないでくだはれ。
ま、exp()だと近似式でやったほうが速そうだね。
365 :
340 :2007/06/06(水) 19:15:18
ところで金融システムをやる人たちはこの辺の技術を ほとんど知らないのだけれど皆さんはどの分野でやられてるのでしょうか?
信号処理とかゲームじゃないかな。 逆に聞きたいのは、金融の分野で応用効くの? 桁数が必要だろうし、スピードよりも可読性が求められそうじゃ無い?
367 :
340 :2007/06/06(水) 23:23:51
金融では最近一部グリッドが導入されだしたようだけど HPC分野はほとんど未開拓な状態だと思う。 またSIMDとかMPIなどは外資パッケージソフトの一部では使われている。 SEへの「もっと計算を速くできないか」との要請に対し 自分の無知なことも知らず「莫大な金と時間がかかる」の一点張りで受け入れられないケースが多い。 このため多くのユーザーは高速化は無理なことと思っている。 という状況下、前にも挙げたようにリスク管理やデリバティブ関連などでは高速化へのニーズは高く、 この辺からHPC化が進んでいくと思う。 現時点では、すぐ欲しい計算結果も下手をすると数日かかるといったことが、あたりまえにおこなわれているから・・・
っていうかmsdn2みたけど VC++だと数学関数はSSE2対応ならSSE2版使ってくれるようになってるみたい? 純正の最適化ルーチンより速くしようと考えるのはぶっちゃけかなり無謀かと。
369 :
340 :2007/06/06(水) 23:57:04
exp()はそれほど問題になっていないからいいんだけど 問題は上に書いたことなんだ。 皆さん、金融システムやらないかい?
仕事にする気はないが話題として興味はあるな。 重たいのはDBとかで、SIMD化するようなものでは無いイメージがある。
そんなのアプリによるのでは?
書き込みタイミングも全体パフォーマンスには注意が必要
373 :
デフォルトの名無しさん :2007/06/18(月) 23:11:59
【派遣ネガティブ根性チェック】 3つ以上、チェックがつけばアナタの性格はひん曲がっており、 ネガティブ負け組派遣人生を歩んでいます。 □派遣先正社員の作った糞開発ツールはたとえ腐っててもマンセーして使う □派遣先の人事権のある社員の意見はたとえ間違っていてもマンセーする □昼食は必ず派遣先の社員と行くべきだ □派遣先から「いつまでもここで仕事してくださいね(安い金でw)」と言われて嬉しい □自社で仕事なんてできるわけがない □派遣労働の問題点の話題が出ると感情剥き出しにして反論する □派遣労働の問題を指摘する人は嫌いだ □派遣先には仕事だけでなくプライベートについてもグイグイ引っ張って欲しい □奢ってくれる派遣先正社員を尊敬する □自分の月額金額を知らないのは当然だ、単金を聞いてはいけない □派遣先正社員より自分の生涯収入が低いのは当然だ □派遣先に尻尾を振り、かわいがってもらうことが大切だ □チビは派遣先にかわいがってもらいやすから派遣には有利だ
ねぇねぇこれSSE使ってかける? int RSHash(string cr) { int b = 378551; //Ramdom Ranges I've chosen (can be modified) int a = 63689; int hash = 0; //Output hash int i; //Temp number that scrolls through the string array for(i = 0; i < cr.length(); i++) //Loop to convert each character { hash = hash * a + cr[i]; //Algorithm that hashs a = a * b; } return (hash & 0x7FFFFFFF); //Returns the hashed string }
PMULUDQか。 2つの文字列を同時に処理するなら使えるかな?
intは32ビットね? MMX/SSE2の掛け算は16ビット×16ビットまでしかできないから 半端に使ってもかえって遅くなるような。 依存関係がきれいに解決できてpmaddwdが適用できれば速くはなりそうだが。
ループの内側を2倍に引き伸ばすとこうか? hash = (hash * a * a * b) + (cr[i] * a * b) + cr[i+1]; a = a * b * b; 引き伸ばしていけば並列演算できそうなところは結構あるんだが、さて・・・ ああ頭いてぇ
SSE入門したいのですが みんなどこから手をつけはじめたのですか?
380 :
341 :2007/06/22(金) 02:34:18
使い方 intrin.hをインクルードすることでSSE3のintrinsicsまでは使える SSSE3のintrinsicsは自前で各命令を定義することで使えようになる 例 #include <intrin.h> /* MMX */ __MACHINEX86X_NOWIN64(__m64 _mm_abs_pi8(__m64)) __MACHINEX86X_NOWIN64(__m64 _mm_sign_pi8(__m64, __m64)) __MACHINEX86X_NOWIN64(__m64 _mm_alignr_pi8(__m64,__m64, int)) /* XMM */ __MACHINEX86X_NOIA64(__m128i _mm_abs_epi8(__m128i)) __MACHINEX86X_NOIA64(__m128i _mm_sign_epi8(__m128i, __m128i)) __MACHINEX86X_NOIA64(__m128i _mm_alignr_epi8(__m128i,__m128i, int)) 問題点 palignr命令の3番目の引数が定数でもエラーにならない
381 :
341 :2007/06/22(金) 02:38:44
>>380 の訂正
問題点
palignr命令の3番目の引数が 『定数でない場合に』 エラーにならない
>>379 俺も最初はこんなのから始めて動作を確認していった。
(この書き方、aがポインタか配列かって区別がややこしいんだが)
#include<stdio.h>
int main()
{
int i,a[]={12,23,34,45};
__asm{
movdqu xmm0,a
paddd xmm0,xmm0
movdqu a,xmm0
}
for (i=0; i<4; i++) printf("%d\n",a[i]);
return 0;
}
>>381 すまん意味不明。エラーにならないならどんなコード吐くの?
384 :
341 :2007/06/23(土) 00:28:50
定数の場合 0f 3a 0f c1 01 palignr mm0, mm1, 1 定数でない場合 0f 3a 0f c1 ac palignr mm0, mm1, DWORD PTR _i$[ebp]
IA-32 SIMDリファレンス買ってみた。 図がいぱい載ってるぞw
>>340 exp(x)=2^(y1+y2)と変換する(y1は整数部y2は少数部)
y2を多項式近似で求めると速くできる
10桁程度の精度でよければ7次で可能
>>465
>exp(x)=2^(y1+y2)と変換する(y1は整数部y2は少数部) それをやるならy1は整数、y2は-0.5<=y2<0.5と選んだ方がよさそうだね。
>>387 そうだね。 ところでy1が正のときはビットシフトで行けるんだが 負の時はいい方法ないかね?
IA-32SIMDリファレンスブック こんな本が出てるね
書店でぱらっと見た感じではSSSE3まで紹介してるみたいだけど これでどうやって下巻を書くつもりなんだろう
誰かSSE2にrcppdとrsqrtpdがない理由を合理的に説明してください
あえて近似解をDoubleで使う必要はないからだろう
SSEのrcpps,rsqrtpsって |相対誤差|≦ 1.5×2^-12 って書いてあるから、 仮数部12bitくらいの精度しかないって事だよね?
rcppsからもってけるから。命令数も倍になるがな。 そして倍精度にそんなトランジスタ割けないというのが合理的理由だろう。
396 :
395 :2007/07/08(日) 01:27:58
あー失礼。トランジスタを割けないという主張は同じなんだが 仕組みとしてはテーブルを引いてるだけのはず。 だから24bitとか32bit分ものテーブルを用意出来るわけが無い。 倍精度を使うような人は精度重視なわけで、 divpdあるんだからどうしてもやりたいんだったらソフトウェアでrcppsから精度上げてくれ、 マイクロコードを用意するのはバカバカしい、ということ。
>>396 能書き垂れてるんだが
結局393と何が違うんだよ
398 :
395 :2007/07/08(日) 08:28:15
>>397 違いは無い。ただ393だけ言われても392が納得しづらいだろう。
テーブルの要素数が
12bit->4096
24bit->1677万
だけ必要であると考えれば物理的に無理な事が納得出来る。
まあマイクロコード組み合わせればできなくも無いだろうけど クロック数かかる上に【近似】解じゃねぇ
>>389 この本買ってみたけど、リファレンスいうから命令全部載ってるのかと思ったら載ってなかった
手元にリファレンス的なものがあるといいなと思って買ったのに・・・詐欺だわー超高いし
401 :
薄汚い派遣の国、日本 :2007/07/15(日) 21:35:53
最近、職場で「出戻り寄生派遣」という言葉が囁かれています。 派遣契約を切られたにもかかわらず「次の派遣先でも切られてしまって生活できません」 などと 言って泣き落としで再契約した派遣のことです。 今月初め、半年前に切った派遣が出社してきてみんなびっくりしました。 影でコソコソ偉い人に泣きついて再契約したそうです。同じ部署の人には黙って・・・ そんなことまでして自宅の近くの派遣先にこだわって人間として恥ずかしくないのですか。 派遣でスキルアップ、派遣で収入アップとか言うなら一箇所にしがみつかず 複数の会社を渡り歩いてください。 ひとつの会社で派遣向けの単調な仕事をしていたらスキルアップなんてありえないでしょう。 身分不相応な商品のローンを払うために派遣だと当然足りない収入は親にも寄生して、 いつ切られるんじゃないかとビクビクしながら人事権のある人間とだけ仲良くし、 契約終了を通知されれば泣き落とし。悲惨な人生ですね。 氏んだほうがいいんじゃないですか。
403 :
デフォルトの名無しさん :2007/07/21(土) 21:32:10
【派遣ネガティブ根性チェック】 3つ以上、チェックがつけばアナタの性格はひん曲がっており、 ネガティブ負け組派遣人生を歩んでいます。 □派遣先正社員の作った糞開発ツールはたとえ腐っててもマンセーして使う □派遣先の人事権のある社員の意見はたとえ間違っていてもマンセーする □仕様とは正社員から口伝されるものだ □口伝された仕様を意図どおり理解できなかったのは自分の責任だ □昼食は必ず派遣先の社員と行くべきだ □自分の仕事で問題が発生しても解決するのは派遣の仕事ではない □派遣先から「いつまでもここで仕事してくださいね(安い金でw)」と言われて嬉しい □自社で仕事なんてできるわけがない □派遣労働の問題点の話題が出ると感情剥き出しにして反論する □派遣労働の問題を指摘する人は嫌いだ □派遣先には仕事だけでなくプライベートについてもグイグイ引っ張って欲しい □奢ってくれる派遣先正社員を尊敬する □自分の月額金額を知らないのは当然だ、単金を聞いてはいけない □派遣先正社員より自分の生涯収入が低いのは当然だ □チビは派遣先にかわいがってもらいやすから派遣には有利だ
SSE2で、ベクトルの各要素ごとに独立なシフト量を設定してシフトを行うことは不可能 という理解で良いですか? a[0] <<= b[0] a[1] <<= b[1] a[2] <<= b[2] a[3] <<= b[3] みたいな事がやりたいんですが。
>>404 処理速度は劣るが、シフトの代わりに乗算で処理するとか。
残念ながらそれだとスカラーよりも遅くなってしまいました。うーむ
そうか。面白そうな問題なので何とかして高速化したいなあ。
>>404 うん無理。AltiVecだとできるんだよねそれ。
下位ビット落ちるけどこんなのはどう? cvttpi2ps→指数部操作→cvttps2pi
410 :
341 :2007/08/25(土) 01:58:03
VC++ 2008のIntrinsicsは Intel SSSE3/SSE4.1/SSE4.2とAMD ABM/SSE4aに対応しているようだ
Intelでいうとsmmintrin.hって奴か。 なにSって。
失礼します。 MMXのシフト系の命令って、ソースオペランドに直値、メモリ、MMレジスタのみですよね? 汎用レジスタ(eaxとか)を書いてもうまく動作しなかった気がするんですが、 VC6,VC8ともに、以下のコードがエラーにならず通ってしまいます。 psllq mm0 , eax 何か勘違いしてますか?
>>413 eaxって書いたところがmm0になってました。
インラインアセンブラのバグ? VC6のころからそうなのに
VC8でも放置してるのはなんか理由があるのかな。
mm0もeaxも3ビット表現の 0 だもの。 汎用・FP/MM・XMMのレジスタ指定はopcodeで決まるから
>>415 逆アセしてmm0に見える理由がそれだとしても、アセンブラの文法
としてeaxって書くべきではないところに、そう書いてエラーにしない
のはおかしいと思いませんか?
movd eax mm0と movd mm0, eax だとどうなるかな。opcodeで区別してるはずだが
その命令は見た目どおりに動くので、特にいうことはありません。
もう32bit fpと整数はAltiVec互換にしてくれよ AltiVecからSSEに仕方なく移ったマカーな俺にはSSEは使いにくすぎる
でもload/storeのアラインメントの扱いが楽なのはちょっといいと思った
SSE4.1でXMM-汎用レジスタ間のデータ出し入れが簡単になるからシフトやローテートは我慢。
>>422 もー出てるなら我慢できるけどさ、まだ出てないじゃん。
それ言っちゃうとBulldozerはおろかBarcelonaすら出てないが
MMXのpmull, pmulhはどういう使い方が想定されているのでしょうか? なんか使いにくそうに思えるのですが……。
>>425 pmull : 16 bit で済む時
pmulh : 小数部 16 bit の固定小数点乗算したい時
xbyakを魔改造するか
だから高いって。
ぼったくりでそれか。マジいらん。
SDK for 45nm Next Generation Intel Core 2 Processor Family and Intel SSE4 にSSE4.1/4.2のマニュアル一式とエミュレーションDLLがついてるからそれで十分。
432 :
デフォルトの名無しさん :2007/10/27(土) 05:20:50
総和を求めるなど、一つの変数が共通の場合、SSEを使って計算するCコードを教えてください
総和なら簡単じゃん __declspec(align(16)) float a[100]; float dest; //SIMD化前 for (int i = 0; i < 100; i++) { sum += a[i]; } //SIMD化後 __m128i sumx = { 0.0f,0.0f,0.0f,0.0f }; for (int i = 0; i < 100; i++) { sumx = _mm_add_ps(sum, *(__m128*)&a[i*4])); } sumx = _mm_hadd_ps(sumx, sum); sumx = _mm_hadd_ps(sumx, sum); _mm_store_ss(sum, sumx);
訂正 //SIMD化後 __m128i sumx = { 0.0f,0.0f,0.0f,0.0f }; for (int i = 0; i < 100; i+=4) { sumx = _mm_add_ps(sumx, *(__m128*)&a[i])); } sumx = _mm_hadd_ps(sumx, sum); sumx = _mm_hadd_ps(sumx, sum); _mm_store_ss(sum, sumx);
movqに対応する組込み関数ってないん?
_mm_loadl_epi64
Σ(・ω・ノ)ノエッ
__m128i _mm_loadl_epi64(__m128i*) __m128i _mm_move_epi64(__m128i) void _mm_storel_epi64(_m128i*, __m128i)
sse4のベンチ見てるとちょっと心配になってくるな。
>>435 MMXのは無い。
__m64 mm0 = a[i]で既にロードに展開される。てか、コンパイラ任せ。
x86の話なんですが 64ビット整数のグローバル変数1つを操作する関数が 頻繁に呼ばれるプログラムを作っています。 アセンブラ見ると、32ビットずつ操作しているようなんですが これをMMXを使っていっぺんに操作するようにすれば、高速化しますか? 高速化するなら、MMX勉強してみようかなと思ってるのですが。
しません
andとかorとかビット演算だけなら可能性がないとも言えない。
関数コールのインライン化のほうがまだ効果あるかもな
2つの4byteのデータを先頭から任意の ビット数一致しているかチェックするのに SSEって有効に使えそう?1ビットずつチェック とかアホ過ぎて uint32_t chk_bit(uint32_t master, uint32_t src, uint32_t bit){ この中どうしよう。 }
【この中】 return ((master ^ src) >> (32 - bit)) != 0;
xmmレジスタを128bit intとして使う場合, あるbitが立っているかどうかを高速に調べる方法はありませんか? SSE4.1でptst命令が導入されますが,それまで待ってられません.
xmm0に調べたい値ががあるとすれば movdqa xmm1, [pattern] movdqa xmm2, xmm0 pand xmm2, xmm1 pcmpeqb xmm2, xmm1 pmovskb eax, xmm0 test eax, eax でeaxが0以外ならビットが立ってる。
pmovmskbに訂正してくだしあ><
THX やはりpmovmskbで移すしかありませんか... Nehalemまでは64bit int x 2でやっとくのが吉?
452 :
デフォルトの名無しさん :2007/12/24(月) 11:21:12
ptestはPenrynじゃね?
LARGE_INTEGER otime, ntime; 〜略〜 double dt = (double)((ntime.QuadPart - otime.QuadPart) * (1000.0f / f.QuadPart)); をSSE使ってVC8のインラインアセンブラで書くとどうなりますか?
どう考えてもスカラ演算だよね
64bit整数を64bit浮動小数点数に返還するSSE命令は 64bitモードにしかありません VCでは64bitモード用のプログラムにインラインアセンブラは使えません
*intrin.hのマニュアルを見ればいいと思うが
SSEで書く利点なくね?
無いな
書けても手間損
ファイヤーウォール作る時に パケット解析するのにSSE使っても 手間になるだけ?
そろそろテンプレ作ったほうがいいんじゃないの。 SSEは大量のデータに同じ処理をかけるときにこそ効果を発揮するんであって 細かい所は従来のx86命令のほうがむしろ速い。
>>460 そういうのに向いてるって話は聞いたことがない。
単一の64bitや128bit値を何回も計算するときは?
汎用レジスタに納まらないサイズ弄るなら効果あるんじゃないの?
アレはあくまで32ビット値を4つ同時に扱うものであって、多倍長扱うならむしろ64ビットモードで汎用レジスタベースでやったほうがいい。
( ・∀・)つ〃∩ ヘェーヘェーヘェーヘェーヘェー
PADDQとかの事だろうけどC2Dでもレイテンシ2だしね 実装はcarry selectあたりだろうか
468 :
451 :2007/12/26(水) 11:18:07
>>452 遅レスだが
ptestはSSE4.1で,PenrynはSSE4じゃなかった?
SSE4はSSE4.1とSSE4.2の両方を含む呼称(正確には、という事になった)
Penrynは4.1のみ
Nehalemは4.1と4.2の両方
>>452 で合ってるんじゃねーの?
470 :
451 :2007/12/26(水) 13:20:32
471 :
451 :2007/12/26(水) 13:22:02
>それほど待たなくて済むなぁ これは価格が手頃になるのを,って意味です
64bit浮動小数点数の配列があったとき絶対値が最大の要素を 求めたいのですがSSE2を使って高速にできるでしょうか? 普段はVC++を使ってますがより高速化できるならアセンブラ もつかってみようかと考えてます。OSはVista(64bit)です。
>>472 x64用ののVC++だとデフォルトでSSE2を使うようになっている。
下のを cl /c /O2 /FAsc test.c でコンパイルして、test.cod を見てみるとまあまあのコードが生成されているぞ。
double maxabs(double array[], int size) {
double ans = 0.0;
for (int i=0; i<size; i++) ans = __max(ans, abs(array[i]));
return ans;
}
>>473 Cだと「for (int i=0;」のところでエラーになるので
#include <cmath>
#include <cstdlib>
を付け加えてCPPファイルにしてコンパイルしてみました。
movsdx andpd comisd
などが使われていますね。これがSSE2かな?
でもこれが本当に高速なコードかどうかはわからないですね。
インテルでMKLというライブラリを出してますがこれはすごいですね。
試したのは行列計算の一部だけ(LU分解)ですが数値計算の本に載っている
プログラムをVC++でコンパイルしたものより5倍ぐらい高速です。
数学レベルで新アルゴリズムを開発した可能性は低いので実装レベル
の技術が高いと思うのです。
5倍の差は大きいのでSSEなどを勉強して何とか近づきたいのですが
大変かな?
dou you make correlated random number?
476 :
451 :2007/12/26(水) 20:38:30
477 :
472 :2007/12/26(水) 23:15:38
>>476 やりたいのは絶対値の最大なのでちょっと違うけどなかなか参考になります。
最大と最小をもとめて絶対値の大きな方をとる方法と
絶対値を計算しながら最大をもとめる方法がありますね。
まあこの辺はいろいろ実験してみないとどれがいいのかわからないですね。
>>473 VC++だとmaxsdしか使わない予感。
>>473 ベースで、arrayの要素が偶数個で128ビット境界にあってるの前提ならこんな感じ
たぶんSSE3くらいは使えるよね?たいしたことに使ってないけど。
#include <pmmintrin.h>
double maxabs(double array[], int size) {
static const union {
__m128d pd;
__int64 a[2];
} mask = { 0x7FFFFFFFFFFFFFFFi64, 0x7FFFFFFFFFFFFFFFi64 };
double ans;
__m128d ans_pd = { 0.0, 0.0 };
for (int i = 0; i < size; i+= 2)
ans_pd = _mm_max_pd( ans_pd, _mm_and_pd(mask.pd, *((__m128d*)&array[i])) );
ans_pd = _mm_hadd_pd(ans_pd, ans_pd);
_mm_store_sd(&ans, ans_pd);
return ans;
}
>>474 SIMD化の方が簡単で面白そうだから目につきやすいんだけど、そこは最後の手段なんだよね。
配列同士の四則演算では極力全ての演算をまとめて行って、代入を1回で済ます。
行列なんかの三次元的なループはキャッシュに入る長方形のブロック単位で処理をする。
そういうところが出来てればSIMD化しなくても前者で最大2倍くらい、後者は計り知れない程速くなる。
480 :
474 :2007/12/28(金) 23:06:10
>>479 気持ちはわかるけど具体的にはどうやるのかな?
短いので高速化したいプログラムをアップしてみる。
#include <cmath>
double LU(int n, double** a, int* ip)
{
int i,j,k,ii,ik;
double t,u,det,*w;
w=new double[n];
for(k=0;k<n;k++){
ip[k]=k;
for(j=0,u=0;j<n;j++){ t=fabs(a[k][j]); if(t>u) u=t; }
if(u==0){ delete[]w; return 0; }
w[k]=1/u;
}
det=1;
for(k=0;k<n;k++){
u=-1;
481 :
474 :2007/12/28(金) 23:08:38
続き for(i=k;i<n;i++){ ii=ip[i]; t=fabs(a[ii][k])*w[ii]; if(t>u){ u=t; j=i; } } ik=ip[j]; if(j!=k){ ip[j]=ip[k]; ip[k]=ik; det=-det; } u=a[ik][k]; det*=u; if(u==0){ delete[]w; return 0; } for(i=k+1;i<n;i++){ ii=ip[i]; t=(a[ii][k]/=u); for(j=k+1;j<n;j++) a[ii][j]-=t*a[ik][j]; } } delete[]w; return det; } 最後のforループが3重ループなのでこの付近が一番スピードに関係してそう。
キャッシュ効率上げればかんり高速化しそうだね
483 :
479 :2007/12/29(土) 23:23:23
恥ずかしながらLU分解はやった事無いんだけど 3重のループでa[ii]のラインはiに依存して切り替わり、 a[ik]のラインはkに依存して切り替わるでしょ。 a[ik]のラインはkにつき1度しか切り替わらないからキャッシュにずっと入ってるけど、 a[ii]のラインはkが同じでもiが変わったら切り替わってしまう。 a[ii]のラインは最大k回アクセスがあるから、出来れば切り替えたく無い。 そこで折衷案をとって、a[ik]をもう少し頻繁に切り替える代わりにa[ii]をもう少しゆっくり切り替わるようにバランスを取る。 バランスを取るというのはどういう事かと言うと、 二次元の処理で1000x1000の要素があった時に 1ラインずつ処理するのではなく例えば100x100のマスが10x10個あるものとして処理する。 (0, 0)-(999, 0)を処理してから(0, 1)-(999, 1)の処理をするんじゃなくて、 (0, 0)-(99, 0)まで処理して(0, 1)-(99, 1)...(0, 99, 99, 99), (100, 0)-(199, 0)のような処理の仕方。 今回はループが3重だから、書き換えると6重のループになって頭は最高にこんがらがる。 しかもラインがipによって入れ替わるみたいだから、こういう手法が使えるのかよく分らない。ごめん。 ipがどう変わるかを事前に必要なライン数分計算出来ればいいんだろうけど。
484 :
474 :2007/12/30(日) 21:31:17
>>483 コメントありがとうございます
少し詳細に480のプログラム(LU1)と
intelのMKLを使った場合(LU2)とをテストしました。
サイズ(n) LU1(VC++) LU2(MKL) 比率
4 0.218μs 1.140μs 0.191
8 0.796μs 2.680μs 0.297
16 4.087μs 7.460μs 0.548
32 0.0246ms 0.0204ms 1.21
64 0.174ms 0.0656ms 2.65
128 1.31ms 0.271ms 4.83
256 10.2ms 1.435ms 7.11
512 82.4ms 9.13ms 9.03
1024 780ms 66.1ms 11.8
2048 7.58s 0.501s 15.1
4096 60.9s 3.79s 16.1
8192 486.5s 29.9s 16.3
CPU:intel Q6700(3.4GHz)
サイズが小さい場合はLU1でもキャッシュの利用効率が高いはずですが
予想どうりLU2との差が小さくなりnがごく小さいときは逆転しています。
たぶんLU2は複雑なやっていてそのため遅くなっているのでしょう。
nが非常に大きくなるとLU1はキャッシュ効率が悪いためLU2に大差をつけられてしまってます。
高速化をめざすならSSEの最適化を考える前にキャッシュ効率を上げる工夫をすべきですね。
となると483のような多重ループのブロック化が必然となるか?
まあ、難しそうなので具体的な方法は少し考えてみます。
うまいアイデアがありましたらまたコメントください。(ややスレ違いになりつつあるが)
ソフトウェア・プリフェッチの話を絡めつつやれば スレ違いにならなずに済むか。
xmm の not を一命令で求める方法はありませんか? ~0 との xor は無しで
488 :
487 :2008/01/16(水) 20:45:05
上げときます
pandnでもダメだよな。 そうなると、周りの命令と絡めて実質的に1命令で済ますことを考えるくらいか。
無理っぽいねぇ.all 1 の定数を read することを考えれば, cmpeq xmm0,xmm0 で all 1 を作る方が速いか?
all 1をロードだとレジスタリネーミングされるので先行実行できる可能性がある。 ケースバイケース。
492 :
デフォルトの名無しさん :2008/02/19(火) 10:43:09
メディアンフィルタを作成したいのですが、 コンパイラがSSEを使いやすいコードはどのように書いたらよいのでしょうか?
メディアンフィルタで自動ベクトル化は難しいなあ。 ソートアルゴリズムをGPUでやるやつみたいに直線的なものにすればやってくれない事は無いけど。 とにかく一番内側のループがベクトル同士の演算になるように心掛ける事。
行列計算をSSEで行った場合の 解説サイトしらないっすか?
a1=3.1 a2=4.0 a3=5.5 a4=6.1 r1 = a1^2 + a2^2 + a3^2 - a4^2 r2 = a1+a2 - a3*a4 +a1+a3 + a2*a4 r = r1+r2 こんなのSSEで解きたいんだけどどうすればいいんだろう
dvec.hの cmpeq()した結果が全て0かどうやって判別するの?
if ( _mm_movemask_pd(cmpeq(a, b)) == 0 )
む〜〜〜 倍精度の絶対値はどうすれば求まるの?
学校の勉強か?ちったあ頭使えよ。 方法1(ロード無し): // a = a < 0 ? -a : a; F64vec2 z = _mm_setzero_pd(); a = select_lt(a, z, z-a, a); 方法2(ロード有り): static const __int64 _0x7FFFFFFFFFFFFFFFLL = 0x7FFFFFFFFFFFFFFFLL; F64vec2 m(*(double *)&_0x7FFFFFFFFFFFFFFFLL); a &= m;
間違った。mは static const F64vec2 m = 以下省略
>>500 あーそういうのがあるのですね
何分あほ過ぎて、あきれてるかもしれませんがどうもすいません。
いいってことよ。 ちなみに絶対値の処理がループに入っていて比率が高い場合はロード有り、 絶対値を取る負荷が低いならロード無しが効率的。 ところで最近rcp_nr()やrsqrt_nr()の精度の低さを嘆いていて もう一段階計算するか素直にdivpsを使うか考えてたんだが ググってみるとdivpsとsqrtpsって最近は6 cycleなのな。typoじゃないのか?速すぎる。 なんかrsqrt_nr()はともかくrcp_nr()って要らない子な気がしてきた。 そもそも何故rcpps, rsqrtpsでVMXみたいに12ビット用意しなかったのかと問いつめたい。 プロセッサは日々速くなるんだから12ビットが最初は大きすぎでも用意するべきだったろう。
6 cycleというのは、2.0 で割るみたいな単純なケースだけじゃないの?
0除算ってどう扱うべきなの? 常にチェックするのかな
>>504 情報が古いが248966.pdfを読んでも13 cycleだぞ。これでも十分速過ぎるだろ。
ちょっと前まで40 cycleだったのに。
こりゃ中では12bitのrcppsを持ってるな。逆数取って精度上げが1回で済めば13 cycleでも納得出来る。
>>505 0除算は数学上定義されていない。
プログラムとか関係なく、机上で数式書いた時点でつっこむべきだ。
定義されていないので、当然答えは自分で用意する事。
1. 0で除算する時点で数式が間違っていたと認識し、方法を改める。
2. 除数が0にならないようなロジックにする。
3. 除数が0になった場合の回避策を設ける。
3-1. c = a / (b + 0.001) のようなかさ上げを行う。
3-2. c = a / max(b, 1) のような下限を設ける。
3-3. c = b == 0 ? 0 : a/b のような特別な取り扱いを行う。
4. 結果がNANかを調べて後から計算に失敗している事を認識する。
3はプログラムに組み入れる事になる。3-2と3-3は当然事前に分かればそこで取り扱えばいいし、直前まで分からなければ常にチェックする。
処理によっては無理に回避するよりも4が重要な場合もある。
gccに#include <dvec.h>ってないんだな icc買うしかないか
>>505 常にチェックしなくても、__try { } で囲んで、
0除算例外を __except() で受ける方法もあるよ。
例外を発生させるようにfldcwやldmxcsrで設定する必要があるけど。
509 :
デフォルトの名無しさん :2008/06/25(水) 14:48:40
複数のスレッドで同時にMMX命令を使う場合に スレッドごとにemmsを呼ぶ必要はありますか? それとも以下のように、複数のスレッドから抜け出た後に 一回だけemmsを呼べばOKですか? #pragma omp parallel for for (int i = 0; i < hoge; i++) { // ここでMMXを使用 (x87命令は使わない) } _mm_empty(); // emmsはこの一回でOK?
510 :
509 :2008/06/25(水) 16:10:01
何かあったら怖いので スレッドごとにemmsを呼び出すことにしました。
マルチスレッドでMMXは未対応だけどな
そのへんはOS依存じゃないの?
いやSSEもMMXもマルチコアとマルチスレッド未対応だろ
マルチスレッド未対応とはコンテキストスイッチへの対応のことを言っているの? MMX/3DNowはx87FPUとレジスタ兼用だから問題無いし、 SSEはFXSAVE/FXRSTORという専用命令があるから、これも問題なさそうだが。
そうじゃねー マルチプロセスならコンテクストスイッチ時にSSE/MMXレジスタが 保存されるだろうがマルチスレッドは一つのプロセスの中で複数の スレッドを走らせるので汎用レジスタ退避しかない
516 :
デフォルトの名無しさん :2008/06/27(金) 01:03:32
マルチスレッドの実装に依存する話だが 少なくとも Linux は大丈夫だったはず ダメな環境を俺も知りたい
Windows 95とか? プロセス間でもだめだしそもそも(ry なんてツッコミはいやん
>>515 1.
>>514 に書いてあるように MMXレジスタ = x87レジスタ なのだから、
MMXレジスタが保存されないなら小数点演算も同様ではないのか。
2.特権ユーザでもない限りコンテクストスイッチを禁止できない。
さもなければ誰でもシステムを強制停止できてしまう。 (例:Windows 3.1)
制御できないとしたら、ではどのタイミングでレジスタを待避すればよいのか。
3.>マルチプロセスなら ... 中略 ... レジスタが保存される
それで、マルチコア非対応になる理由はなに?
シグナル(割り込み)とスレッドの区別の付かない人っているよね。 MMXのレジスタをFDPと共有させたのはOS側の対応を不要にするための 仕掛けだったのだけど今となってはやっちゃったって感じの仕組みと評価されている。
521 :
519 :2008/06/27(金) 08:30:11
おっと、
>>515 は対応してない(できない)と言っているのに、
2番ではやり方を聞いてしまってるな。
この質問は撤回するとして、代わりに3番に追加しておこう。
マルチコア非対応というのはマルチプロセッサ(ユニコア)
ならばOKということか?
SMT(ハイパースレッディング等)の場合はどうなのか。
基本的にシングルコアでのみ利用可能だ
新種のキチガイが暴れてるなwww 動かないっつーのが明記されてる資料出せやw
>>522 まず訂正するとユニコアなる単語はシングルコアの誤りだ。
そんで微妙に通じていないようだからもう一度聞くよ。
複数のシングルコアのCPUを搭載したマルチプロセッサの
システムでMMX/SSEは利用可能なのか。
シングルコアなんだけど擬似的にマルチプロセッサの
ように振る舞うSMT対応のCPUではどうか。
具体的に言うとHT有効なPentium4でMMXは使えるのか。
結論だけではなくて、理由を教えてもらいたいのだが。
誤解のないように追記。 話を簡単にするためマルチプロセスの場合を聞きたい。 とりあえずこの件についてはマルチスレッドは保留で。
マルチプロセスの場合は 物理CPU1つだけで稼動する 物理CPU2つならそのうち1つだけ 4つならそのうち1つだけ
脳内仕様はもういいよ、資料出せ資料を。
>>496 亀レスだけど、どのへんが難しい?
単精度の場合だけど
;; r1 = a1^2 + a2^2 + a3^2 - a4^2
movaps xmm0, xmmword ptr [a1_a2_a3_a4] ;; a1, a2, a3, a4を並べておく
movaps xmm1, xmm0
xorps xmm1, xmmword ptr [MASK_PPPN] ;; MASK_PPPN = { 0x00000000, 0x00000000, 0x00000000, 0x80000000 }
;; これで xmm1 = { a1, a2, a3, -a4 } になる
dpps xmm0, xmm1, 0xF1 ;; 内積をとる
;; SSE4.1非対応ならdppsはこれで代替(SSE3必須)
;; mulps xmm0, xmm1
;; haddps xmm0, xmm0
;; haddps xmm0, xmm0
;; SSE3が使えないなら・・・メンドイ・・・
;; r2側は大して並列化が期待できないのでスカラでやってよし
;; r2 = a1+a2 - a3*a4 +a1+a3 + a2*a4 = a1+a1+a2+a3 + (a2-a3)*a4
movss xmm1, dword ptr [a1]
addss xmm1, xmm1 ;; a1+a1
movss xmm2, dword ptr [a2]
addss xmm1, xmm2 ;; (a1+a1) + a2
movss xmm3, dword ptr [a3]
addss xmm1, xmm3 ;;
subss xmm2, xmm3 ;; a2 - a3
mulss xmm2, dword ptr [a4] ;; (a2-a3)*a4
addss xmm1, xmm2 ;; r2 = = (a1+a1+a2+a3) + ((a2-a3)*a4)
;; 最後はこう
addss xmm0, xmm1 ;; r = r1 + r2
>>526 回答は1件だけとか、理由を言っては駄目とかいう戒律でもあるの?
>>515 でマルチスレッド非対応の原因として、コンテクストスイッチで
レジスタの内容が保証されないことを挙げているが、一方で
マルチプロセスならレジスタは保存されるとも言っている。
レジスタがきちんと保存されるならMMX/SSEを使わないプログラムと
何も違わないのに、なぜ一つの物理CPUに縛られるのか。
そんでどのCPUに固定的に割り当てられるのか。
そもそもその割り当てをするのはOS,CPU,アプリのうちどれ?
OSかCPUならその名称、アプリならAPIの名称を教えてくれ。
すくなくとも最後の質問にだけは答えてほしい。
>>524 HT Pen4はおろかCore 2 Quadでも余裕で使えてるから問題ない
Core 2上だとXMMレジスタ使ったときのちょうど半分のスループットだけどな
>>526 あ、526では"物理CPU"と書いてあるね。
>>524 の質問には両方答えてあったのか。
すまない。 上の 2行目前半部分は、撤回する。
それと上でCPUなら名称を教えてくれと言ったがCPUのモデル名
ではなくて、振り分けを担当する機構の名称を聞きたかった。
(デコーダ、スケジューラ、実行ユニット等)
不注意な点が多いのは申し訳ない。 以後気をつける。
そもそもコンテクストスイッチのときにMMX/FPステートの退避・復帰もやってるって
>>530 いや、使えるのは知っている。
ていうか使えないと主張しているのが1人いるだけ。
っつーか >MMX/FPステートの退避・復帰 をやってない処理系があるって主張してる子がいるんだろ
>>535 仮にそんな処理系があったとして
MMX/SSEがマルチスレッドに対応していないことには
ならないよな。あくまでそのクソOSが対応してないだけであって。
つーか、バカバカしいので打ち切りの方向で。
他にも
>>526 とか不可思議な主張してるから、どうしたら
そんな世迷い言が出てくるのか聞いてみたくてね。
>>529 の回答がソフトウェアなら糞環境乙だし、ハードなら
そんなもんあるわきゃないので、たぶん返答はないだろう
けど、あっても次で終わるさ。
はぐらかすようならもう相手にしない。
Core2って1CPUにつき レジスタ何本まで同時に使えるの?
わかるように質問してくれ CPUというのはコアなのかダイなのか? ニモニックから指定できるレジスタは固定だがどういう意味のレジスタなんだ?
xmmmmってやつ
Core 2は3つの汎用ALUと1本のロード・1対のストアがある。 まさにその数分のレジスタが同時に使えるんだよ。 というのも、説明すると add eax, 3という操作があるとする。 実レジスタファイル上のeaxにマッピングされた領域から値をロードし、3を加えて またeaxに格納するってのを1サイクルでこなすのは実際は無理。 ショートカット用のレジスタ(要はアキュムレータ)に値を残すことによって、 次の命令ですぐにeaxの値を参照できるわけだ。 つまり1サイクルってのは実レジスタではなくアキュムレータの更新にかかるサイクル でしかない。 それ以上になると、実レジスタの読み書きの分待たされるので遅くなるわけ。 で、そのショートカットレジスタは実行ユニットの個数分だけある。 64bitでの性能が伸び悩むのも同じ理由だよ。 レジスタ個数が増えた分、レジスタ間オペレーションのインターリーブがしやすくなった。 でもそれによってショートカットの有効利用ができなくなる。 増えたレジスタを有効に使おうとすればするほど、実レジスタファイルへの読み書きが増え、 高速化が使えなくなる。 ちなみにNehalemでは若干改善されるみたいだが。 おそらくは同時にショートカットできるレジスタの個数が増えるのだろう。
Core 2に限らずP6シリーズは伝統的にこの仕様なんでまあ細かいことは気にするな
つまり糞ってことだPowerPCと比較して 糞すぎるんだよなぁ
544 :
デフォルトの名無しさん :2008/07/30(水) 21:25:16
3D Nowの機能を使ったエンコードソフトなどありますか?
午後のコーダ mencoder ffmpeg
>>509 の辺りをちらりと読んでアレレ?と心配になってしまいました。
でも、考えてみたら、タスクスイッチのときに、
今のコンテキストの情報(全レジスタ丸ごと)をメモリにコピーして
スイッチ先タスクのコンテキストの情報を丸ごとメモリから読み込む訳だから、
コアが幾つあっても、タスクを実行するコアが入れ替わっても、
全然問題ありませんよね。
上によってタスク(スレッド)毎に別のレジスタセットをそれぞれ持っているような状態が作られる訳だから マルチタスク環境での MMX/SSE の使用は問題なくて、 ただ、スレッド開始時のコンテキストの情報がどうなっているかは、環境依存だろうから、 スレッド開始時にフラグを設定しなおした方がいいという事ですよね。 複数の CPU がある場合でも、タスクを実行する CPU が入れ替わらなければ、1 CPU の時と同じだし、 タスクを実行する CPU が入れ替わる場合でも何らかの形でコンテキストの情報丸ごとを受け継がなければ、 タスクの続きを正常に実行できなくなるわけだから、アプリケーションを作る プログラマが心配するような事では全くありませんよね。 なんかグダグダ書いてしまいって、見苦しいですよね。 御不快でしたら、スルーして下さいよね。
うるせーペニス
8bit単位のシフトつけてくれ 明日までに欲しい
32bit幅の配列があり、 指定の下位nビット(1 <= n <= 32)以外のビットが立っていないときに、 その配列をnビット幅の配列としてメモリ上にギチギチに詰める& 詰めたものを32bit幅の配列に戻す、ということをやりたいです。 詰めるフォーマットは自由で、 詰め元・復元先について先頭のalignmentは揃えられます。
そうですか。
そうですね
やればぁ
>>343 PowerPC(970以降)は命令間レイテンシが大きいからそれはそれで
隙間埋めるのが大変なんだがな。
1回だけ使うデータのロードだけでも1命令分使っちゃうこととか、
32ビット即値をレジスタにセットするのにも2命令かかったりとか、
いざ使ってみるとパフォーマンスにかかわる制約が多すぎる。
Int/FP/SIMD各32本とレジスタ本数が多いのが逆に災いして
レジスタリネーミングそのものも弱いから、高速化のためには
レイテンシ隠蔽のため静的なアンロールに費やされることになり、
結果的にはx86に対するレジスタ本数差分の優位すら覆されてしまう。
ジョブズの「今までの○倍」ってプレゼンもあながち誇張でもない。
ものによっては確かにそれくらいIntel CPUのほうが性能が出る。
命令セットは汚く論理リソースは限られてるが、その分だけ逆に
アグレッシブな動的最適化技術が比較的有効に働くからね。
Java仮想マシンがスタックマシンなのだって、スタック構造は
並列度を抽出しやすいから。また、論理レジスタが少ないほど
アウトオブオーダ・レジスタリネーミングのリソース管理が楽。
もちろん、静的な最適化で事足りるならそれに越したことはないんだが
実行ステージのパイプラインが深くなったりするたびに再コンパイル
(最悪の場合再コーディング)してられないなど、「コード資産」
という名の制約もあるからね。
Intelのx86は新命令を取り入れつつも、既存のコードもコンパイル
しなおさなくてもある程度は速く走ることを主眼に改良してきたから、
いろんな処理を無難にこなせるわけだ。
PPC信者に触っちゃいけません
PowerPCのアセンブラって、Z80から入った俺にしてみたら すっごくわかりやすかったんだよなぁ 信者になる気持ちもわかる
558 :
デフォルトの名無しさん :2008/11/15(土) 22:15:50
SSE組み込み関数のラッパーを作ったんで 簡単なベンチとったら↓以下のようになった。 SIMDに有利な内容だったとはいえ、SSEは結構すごいんだな floating_point time = 0.012824 std::valarray time = 0.137409 packed_value time = 0.000011
あまりに差が大きいんで、 ベンチを見直したら↓になった そりゃそうだよね orz float time = 0.036192 std::valarray time = 0.117789 packed_value time = 0.026709
_mm_movemask_epi8に 0x00000000000000FF0000000000000000 渡すとなぜ0x8000になるのですか?
>>560 ならないはず。
__m128iにそのデータをセットして_mm_movemask_epi8を
呼び出すまでのコードをアップしてみて。
>>561 えーと上のコードだと以下の計算で会ってますか?
(0x00 >> 7) << 15 |
(0x00 >> 7) << 14 |
(0x00 >> 7) << 13 |
(0x00 >> 7) << 12 |
(0x00 >> 7) << 11 |
(0x00 >> 7) << 10 |
(0x00 >> 7) << 9 |
(0xFF >> 7) << 8 |
(0x00 >> 7) << 7 |
(0x00 >> 7) << 6 |
(0x00 >> 7) << 5 |
(0x00 >> 7) << 4 |
(0x00 >> 7) << 3 |
(0x00 >> 7) << 2 |
(0x00 >> 7) << 1 |
(0x00 >> 7)
0x0100 なんで0x0100するの?どこにもそんなこと出てないけど
たぶんさ、 デバッグウィンドウに出てきた16進ダンプをビッグエンディアンだと思い込んでるんじゃないの? 00 00 00 00 00 00 00 FF 00 00 00 00 00 00 00 00 を0x00000000000000FF0000000000000000だと勘違いし 80 00 を0x0080じゃなくて0x8000だと勘違いしてると。
そうだったりした 許してください
567 :
デフォルトの名無しさん :2009/01/19(月) 10:10:01
何でnotがないの? 何でandnotがあるの? 実用的にはこの方が都合いいのかい?
FFFFFFFF・・・・とXORとればNOTになるからじゃね?
本当にだんごさん?
こんなレジスタが糞少ないアーキテクチャで0xFFFFFFFFとのXORとか言っちゃう団子さんって…ぷぷ。 まあnotした値はまた何かと演算する事が多いので xorとandnotがあれば殆どの場合は事が足りるというのが理由かと。
別に糞団子の肩持つわけじゃねーけど、XORPS/XORPDの第2オペランドはアドレス指定出来るからレジスタなんか使わんぞ?
んまあそれでもいいけど、他の変数とxorとかandnotする事の方が圧倒的に多いでしょ。 それにload使っちゃうのが勿体ない。
573 :
デフォルトの名無しさん :2009/01/20(火) 11:17:34
>>570 確かに言われてみれば結果の正負問わなきゃand
or
xor
andnotであらゆる2値論理演算を1命令で出来るな。
でもやっぱり釈然とせんなぁ…
普通にnotより要らない命令ありそう。
andnotてnandのこと? 実際の回路作る時にはandよりnandの方が作りやすいんだそうな。
>>574 安藤能登と難度は別物
AND-NOT: A & ~B
NAND: ~(A & B)
てかいい加減MUXが欲しい。
(A & B) OR (A & ~B)
>>572 pcmpeqb xmm0, xmm0
pxor xmm0, xmm1
おkwwwwww
>>567 他の命令で容易に代用可能な処理にオペコード割り振る余裕がないから
lddquのプリフィクス違いとか、2byte Opcode空間にも若干空きがからNORとかNAND充てようと思えば出来なくもないはず
団子さんはGUGPUとかSSEみたいなケチってるのじゃなくて本格的なSIMDの方はやんないんですか? ある程度Cッぽい文法でお手軽になってきたようですけど。
さすが団子さん! 途中で書き換えたから少し分かりにくい文になってますが、 SSEはケチってますが、GPUはケチってるわけじゃありません。 CELLだと演算結果をPCの方に持ってこれませんよね。 もしかして物理演算(フィズクス)の方もやっちゃってるんですか?
ケチだよ。ローカルメモリの空間がCellより狭すぎ。
ローカルメモリって言うのはレジスタのことですか?それともキャッシュ? インテルのマニュアル読んでいて気がついたんですけど、 最近はSSEユニット搭載PCがだいぶ多くなってきたので、レジスタも多くなったと考えられませんか。 つまり、汎用レジスタは従来どおりIO関係とアドレス計算専用としておいて、 FPUは使用せず、MMXを整数計算(64bits)専用、SSEを浮動小数計算専用とすればそれぞれのユニットは直交してるので、 従来のインテルみたいなレジスタが少ないアキテクチャでもその概念で使うと多少は変数(レジスタ)が増えるかなって思います。 その代わり80bitsじゃないですけど、FPU使いたいときはいつも通りです。
ただこういうレジスタ割り当ては、人間の手じゃなくてコンパイラがやることなのでなんともいえないんですけど、 団子さんみたくアセンブラ職人だとレジスタ使い放題なんじゃないですかね。 といっても、職人団子さんがsimdコンパイラとかライブラリ作ってくれればそれまでですが。 それと、SSEと比べるならSIMDはGPUの方が5倍10倍以上速いし、アライメントとかも含めてだいぶ職人の英知が必要なので、所詮は小手先業かなって感じですけど。
585 :
,,・´∀`・,,)っ-○◎● :2009/01/20(火) 23:37:18
ふざけんな誰がそんなことやるか
団子はツンデレ
>>583 指摘されるまでもなくSSE使う時点で従来の整数レジスタはアドレスとループカウンタに総出でかり出されてる。
アドレスとループカウンタにレジスタ8つでもギリギリ足らないくらいだから、今までがいかに足りてなかったか考えるとやっぱこの変態アーキは笑える。
で、例えばAthlon系で3DNowとSSEを併用しても速くならないんだなこれが。
整数SIMDと浮動小数点数SIMDで演算器が分かれているわけでもないから、
MMXを整数、SSEを浮動小数点数としてもメモリアクセスの軽減以外に効果はあまりない。
というか、Cellみたいな1要素がスカラとしても扱える便利なアーキテクチャでも無い限り
浮動小数点数の演算が重要でSIMDを導入しよう、って箇所において整数SIMDが出てくる事なんてまずないと思うんだ。
レジスタが固定してるってのは、手動で直接アセンブラ使うときはどのレジスタに置くかって悩まなくて済むからプログラムしやすいってのことはある。 結局どれぐらいPGがプログラムしやすいか(管理しやすいか)てことかと思う。 storentapsみたいなキャッシュ効率をいちいち管理するとかはPGの仕事じゃなくてハード(それぐらいアキテクチャの組み込んどけ)の仕事かな。 ただ他のアキテクチャでもメモリからフェッチするわけで、どのハードを使ってもフェッチする以上計算じゃなくてメモリ転送の差じゃないのかな。 アセンブラに頼るような設計はしないし、アセンブラは直接使わないでコンパイラ任せだからあまり関係ないけど。
>>567-570 もっとレジスタの糞少ないi8080で、XOR AとかやってたんだYo!
592 :
,,・´∀`・,,)っ-○◎● :2009/01/21(水) 10:40:09
> 指摘されるまでもなくSSE使う時点で従来の整数レジスタはアドレスとループカウンタに総出でかり出されてる。 > アドレスとループカウンタにレジスタ8つでもギリギリ足らないくらいだから、今までがいかに足りてなかったか考えるとやっぱこの変態アーキは笑える。 それは無いわ。何の計算やってたらそうなんだ? どうせ多重ループとかやってんだろ?外側のループカウンタなんていちいちレジスタに置いておくなよ。 Pentium M以降のIntelアーキはスタック管理専用のハードウェアを備えてるからpush/popを 高速でこなしてくれる。 > というか、Cellみたいな1要素がスカラとしても扱える便利なアーキテクチャでも無い限り あれのどこが便利なんだアレが。 MM/XMMレジスタでも最初の要素をmovd/movqで汎用レジスタに転送できるだろ?たかだかレイテンシ1で。 なんならpextrdでもどうぞ?あとptestで分岐条件レジスタ操作できるけど何か? 君、頭弱いでしょ。
誰 が ア セ ン ブ ラ で や っ て る と 言 っ た 多重ループなんてコンパイラが自動的に最適化するだろう。 実計算をやった事がない負荷ベンチマーク厨は黙ってろ。
ヴァカが発狂したな
Celllが実演算(笑)向けなんだ(笑)
といっても、団子はただの「負荷ベンチマーク厨」であることに変わりはないが?
実演算(笑)ってなんですか?
じつえんざん なのか みえんざん なのか 根本的な問題として 実演 算 なのか 実 演算 なのか
実演算を ぐたいてきに 実演してくだサンせ
おーい実演販売まだー?
冷静に自分の連続投稿を読み直せ
実演販売まだー?
まあいいや 自分でレジスタの割り当ての管理はできなくても組み込み関数くらいは使えるでしょ。馬鹿じゃないんだから。 っていうか、組み込み関数なしでMMX/SSEを適切に使ってくれるコンパイラって無いけど。 CellやGPUよりx86のほうが圧倒的に楽だよ。
おまえはアセンブラ使わないとただのヴァカのようだなw
君はどうやら常時ヴァカだな
何と比べてx86の方が楽なの?
>>605 誰に対していってるか不明だけど、もしかして人違いしてないか?
>>606 CellやGPUより
ニホンゴヨメマセンカ?
GPUが万能で全てのSIMD演算を高速に行えると思い込んでるヴァカは相手にしたくない。
いやな制約だらけ。
>>608 いや。そうじゃなくて、CellやGPUと、x86の何(の機能)を比べて圧倒的に楽かていってるわけ?
x86はSIMDを念頭においた設計から始まったわけじゃないから、そもそも比べるところないんだけど、どこを比べてるのかな。
まず一つとしてメモリ階層の管理を、パフォーマンス上重要でもないようなところまで 明示的にやらないといけないのがはんざつ(麻生語ではない)。 それ以上でもそれ以下でもない。 キャッシュ汚染を抑えたい箇所でprefetch*やmovnt*を使わなくなって遅くなるだけで別に死にはしないが Cellだとスクラッチパッドメモリの容量超えたらアウトなんだよ。 CUDAは言語レベルである程度抽象化されてはいるが、本質的なハードの制約にはCellよりもっと厳しい。
>>611 その部分は人の手でやるとかネイティブを直接扱う(キャッシュ・メモリ管理する)んじゃなくて、まず初めにライブラリとかのツールを作ってコンパイルするアプローチじゃないの?
そういうのがそろっているからこそ、扱いが圧倒的に楽といえるんじゃないか。
その分直接扱うときに比べれば冗長が生じるけど、楽したいわけだしその辺はトレードオフ。
諸君 私はGPGPUが嫌いだ。 諸君 私はGPGPUが大嫌いだ。 低容量のシェアードメモリが嫌いだ 低容量のコンスタントメモリが嫌いだ if文なのに分岐しないプレディケート機構が嫌いだ switch文ですら分岐しないプレディケート機構が嫌いだ やたら多いけど自由に使えないレジスタファイルが嫌いだ 低クロックなシェーダコアそのものが嫌いだ CUDAで OpenCLで Brook+で CALで Compute Shaderで この地上で行われるありとあらゆるGPGPUが大嫌いだ
そんな食わず嫌いだと世の中から取り残されちゃいますよ。スピード狂さんw
そもそもGPGPUとかスレ違いですから。乞食は消えてくれ
団子、自作「実演」自重しるww
特に
>>613 とか頭悪過ぎる。スパンコだと思えばむしろ普通じゃん。
せっかく昼間っから粘着できるニートなんだから、何でもアセンブラ
職人として腕を磨けば良いのに。
とりあえず団子は書き込む前に自分の文章見直せ、今に限らず なんていうか、素でキモイ。 折角持ち合わせた知識スキルを人の気を害する使い方すんなよ。 ただワガママで周りが見えてない馬鹿に見えるぜ。
618 :
,,・´∀`・,,)っ-○◎● :2009/01/22(木) 05:38:37
嫌いなものは嫌いだしスレ違いの物乞いは見苦しいだけ
619 :
デフォルトの名無しさん :2009/01/22(木) 10:09:57
知ってるか?ここはアセンブラスレでもSIMDスレでも高速化スレでもましてやCellスレでもないんだぜww
この板の全てのスレは 団子さんの自己表現用ですっ!
計算が演算に見える顔文字コテは眼科行ったほうがいいよな… そのまえに脳ミソが癌化してる気もするがw
んー、こりゃあんたらの負けだな 素直に退散するこった
623 :
デフォルトの名無しさん :2009/01/23(金) 00:06:40
鳥取て朝鮮の属領だっけ?
624 :
デフォルトの名無しさん :2009/01/23(金) 09:45:32
8bit単位のshuffleがほしい つかそれ以前にSSEのshuffleて癖あるよな?
moventpsって効果あるんですか? コードにもよるんですが、ベンチをしても、gcc -O1, O2, O3 でそれぞれ異なるんで挙動を測定できないんですが。 それと、fenseとかキャッシュ制御も測定値(最適化つかう・つかわないときのベンチ)が一定してないのでイマイチ効果があるかわかりません。
あるよ。 【movnt*が有用なケース】 既にL1キャッシュに載っかってる見込みで、そのままキャッシュに保持したいデータがある。 なおかつ、ストア先のアドレスは、キャッシュに載っかってなおらず、ストアしたデータを すぐに再利用する予定もない。 ストア先のアドレスのアクセスがシーケンシャルでない場合は、汚染を防ぐ意味では特に有用。 movntでないアクセスをすると、該当アドレスはL1にフェッチされてしまう。 フェッチされた分、L1にもともとあったデータがL2以下にパージされてしまう可能性が高くなる。 【もっとも移植性の高いprefetcht0の代替方法】 volatile int tmp; for (int i = 0; i < array.size(); i++) tmp = array[i]; 簡易的にはキャッシュラインのどれかにタッチしてればL1に割り当てられるので、サイズに応じて 32バイトとか64バイトとかのストライドでタッチすればいい。 普通はprefetch*を使いますけどね
マニュアルのとおりなんですが、それを実測すると(それも最適化有効・無効などで)挙動が不確定なのでそもそも測定不可能ということです。 測定不可能(不安定)なのにベンチすることも出来ないわけで、マニュアル記載の理論上の話ではなく、 実際にそのキャッシュ汚染を考慮したコードを組み込むだけの効果があるかどうかなんですけど。 ベンチをするサンプル・コード(や最適化オプション)によって全くベンチ結果が違うってことも分かります。 ただ、SSEを使うコードは巨大配列(64KB以上とか)が普通で再利用しないのでmovntps効果ありそうなんですけど、思ったほどでもありません。 そのような巨大配列はアライメントなど普通はされてないので、どうもprefetchやmovntpsの使いどころが分かりません。
最近のCPUはキャッシュが大きめで自動的なprefetchとか、キャッシュのプライオリティ管理とか優れてるから 数十MBとかそれ以上の単位にならないと効果は実感できないかも知れない。 シーケンシャルだったり定ストライドだったり、アクセスに程度パターン性があればCPU側が勝手にやってくれる。 そう言う局面でprefetch*を変に使おうとすれば却って遅くなることもある。 効果がないと思えば、使わないのも手ではある。
数十MBは、例えば90MBをメインメモリ上に常時確保するってことなので3Dゲームでもあまり現実的ではありません。動画用途とかなら分かりますが。 つまり、動画とか3DゲームならSSEを使うまでもなくGPUとか他を使うわけで、SSEは全く意味ないってことじゃないですか? いまのところ画像ファイルにSSE適用することを考えてるので、アライメントされてない配列は高々9MB程度なんですけど、キャッシュ汚染を考慮したコードを書いても2,3倍高速になるわけではないようです。 まだあまり試してませんが、せいぜい5%程度速くなるところでしょうか。 なので、このインテルが提供しているキャッシュ制御機構は、どういうときだと劇的な効果(storeupsに比べて2倍高速とか)が出てくるんですか?
SSEが出てきたときにはGPUによる動画支援とか無かった時代だからね。 キャッシュも256KBあればいいほうだった。 メモリ帯域も狭くて、それ故にその256KBに収まるかどうかどうかがパフォーマンスを 大きく左右した。 なんせ、Pentium IIIはCellのSPE程度のトランジスタ数しか備えてなかったからね。 明示的なキャッシュ制御命令の使用の効果はCPUの進化により、劇的なものは見られなくなった。 逆にいうと、ハードウェアの進化により、明示的なキャッシュ制御命令を使わないことの デメリットが小さくなったってこと。これは好意的に解釈していいこと。 それでも5%程度あるならまだまだ意味はあるわけだが、どう解釈するかは自由。 もちろん、もしCPU以外のハードウェアによるアクセラレーションが使えるなら それを使ってもいい。
たぶんなんですけど、メインメモリ間の転送がCPUのキャッシュに比べてそもそも遅いので、 PGがCPU側のキャッシュメモリL123の管理(汚染など)を考慮しようがしまいが、 その効果も相殺されるってことなのでしょう。
そういえばmovnt*ってアラインメント必要だったっけな。 ミスアラインアドレスに対してテンポラルストアを使う場合は、palignrを使って補正してからストアすると速い。 ただしSSSE3をサポートしてないCPUでは使えない。 AMDだとPhenom以降はmovntss/movntsdが使えるからこっちを試してもいい。 どんだけ効果あるか疑わしいんだが。
>>631 >明示的なキャッシュ制御命令の使用の効果はCPUの進化により、劇的なものは見られなくなった。
それはただL2 L3 キャッシュの容量が大きくなって、実用上十分なキャッシュ容量となったからではないか?
意味は無いけど、馬鹿デカイ領域を埋める場合、 movdqaとmovntdqを比較すると、結構違う。
ああ、write-allocateしないから、こうなるのか。
SSE組み込み関数を使って 特に何も工夫のない三角関数を作ってベンチを取ったところ _mm_prefetchと_mm_stream_psのペアがないものは 標準Cライブラリ以下の速度で ペアがあるものは、3倍程度になった。 この結果から、SIMDはプリフェチがないと使い物にならないしろものだと 思ったけど違うのかな?
違うんだろ。
初心者がプリフェッチ必要なプログラム組むってどんなん? なんか変な処理してるとしか思えんのだが
640 :
,,・´∀`・,,)っ-○◎● :2009/01/23(金) 22:23:32
>標準Cライブラリ 現行のMSVCRTの数学関数は内部的にSSE*使ってるけど? 何のアルゴリズムの工夫も無くSIMD化しただけでは勝てなくても不思議ではないよ
>>639 単純にベンチ用。プリフェチの効果を確認したかっただけです。
内容も64kb先読みしてるだけです。
>>640 最適化オプションで、SSEのスカラ使用状態になってるはわかってる。
でも一応俺のはSIMD化されてる訳でしょ。4倍のアドバンテージを
アルゴリズムだけで覆すってのも、難しい話な訳で。
現行のVCの2008 Standard以上ならMSVCRTのソース読めるでしょ。何やってるかはわかると思うけど。
話題逸れるが、MSのはSISDだしintelのlibmは自動ベクトル化のみでSIMD版が公開されてないから使い物にならんと思うのだが団子はどう思ってる? 俺が聞きたいのは団子が他のライブラリを使っているとかいう回答ではなくて 標準や引率すべきコンパイラメーカの努力不足/整備不足をどう思っているか。
MSVCRTよりも遅いってのは、どうみてもコードの書き方に問題あるようにしか思えないんだが。 データの再利用頻度の高い処理なら明示的なprefetch/non-temporal storeなんざ使わなくても 単純2倍以上の性能向上は得られるよ
template< uint_t _num_element, typename _element_type > __forceinline packed_value< _num_element, _element_type > __fastcall cos( /*[in]*/const packed_value< _num_element, _element_type >& v ) { typedef packed_value< _num_element, _element_type > p_t; p_t x; uint_t i = 0; if( sizeof(p_t) > p_t::cacheline_size ) { const uint_t num_split = p_t::cacheline_size / p_t::unit_size; while( i < p_t::num_unit - num_split ) { _mm_prefetch( (const char*)( &v.unit(i) + num_split ), _MM_HINT_NTA ); _mm_prefetch( (const char*)( &x.unit(i) + num_split ), _MM_HINT_NTA ); uint_t j = 0; for( ; j < num_split; ++j ) _mm_stream_ps( (float*)&x.unit(i), cos( v.unit(i) ) ); i += j; } } for( ; i < p_t::num_unit; ++i ) _mm_stream_ps( (float*)&x.unit(i), cos( v.unit(i) ) ); return x; }
packed_valueってのは、SIMD版valarrayのようなもんで 1024要素のcosを計算してる。 これのプリフェチがない奴は、std::cosの1024ループに負ける。 cosの実装は教科書どおり n != 0 : ( power< n >( value_type(-1)) / factorial< 2*n, value_type >() * power< 2*n >(x) ) + value< n-1 >( x) n == 0 : 1 変数の再利用性は皆無なので、プリフェチないと駄目なのかな?
ただアルゴ(笑)が悪いだけだと思うけど。 その教科書だけど、SIMD用の公式も使ってみた?
全ソース見ないことには・・・
なんとなくアセンブラ読んでみると無駄な計算してそうな気がする
明示的なプリフェッチで改善されると言うことは、根拠はないがワークメモリがキャッシュ境界を跨いで
何度も再利用されてる気がする。
とすれば、アセンブリコード吐かせてスタックフレームサイズをどれだけ食ってるか見てみると面白いことになってるかもしれない。
テンプレート使うと、結構膨れあがることがあるんだわ。
>>648 割と素直なFFTのほうが性能出るかも知れないね
ハードウェアプリフェチ無い古いCPUだとprefetch命令で劇的に改善するんじゃね?
いつの時代のCPU1と いつの時代のCPU2を 比べるつもりだ?
>>644 すまん。
三角関数とかのSIMD版がライブラリに入ってはいるのに内部的に使われるだけでヘッダが公開されてないんだよ。
自動ベクトル化はちょっとしたマスク、分岐、std:maxとかが入っただけで諦めてスカラ演算する糞仕様だから自分でSIMD化するわけだが
その時に基本的な数学の関数くらい用意してくれよと。
特にintelのコンパイラは内部的には持ってるんだから。
そこはアレだ、スタティックリンクライブラリを逆ア(ry げふんげふん
そんなことしなくても他のライブラリ使ってるからいいんだ。 そうなじゃなくて、CPUを作ってるメーカーがこのていたらくはなんだと問いたいわけ。 公開しないなら公開しないで、自動ベクトル化を完璧にしろと。
Visual C++は自動ベクトル化そのものをやってない。 Intelとのライブラリ共有の協定でもあるんじゃないかと思ってるんだが。 SIMD周りの組み込み関数の対応だけはしっかりしてるよMSは。
×しっかり ○こっそり だと思うのは俺だけ?
>>652 テイラー展開とかを駆使して関数を実装することも出来るが自分でメンテするのも面倒だろ?
素直にintelのコンパイラ買えばよろし。
ビジネスチャンス
>>655 それどころかご丁寧にfloatをdoubleに拡張しやがる。
俺にはお節介な機能だけど、ちょっと感動を覚えた。
661 :
デフォルトの名無しさん :2009/02/01(日) 17:04:24
過疎ってるなw GCCで __m128d x={290,320},y={199,1000}; x+=y; みたいに関数不要でパック演算が通ったんだけど、 これってintrin系ヘッダーが提供された頃からずっと出来たの? それとも、最近のGCC拡張?
GCCだけ。 同様にAltiVecやSPUでも加減論理など一部の組み込み関数をC演算子で代用できる。
的を外すのは 天然なのかワザとなのか……
日本語が読めないのもあるが、僕ちゃんの知識を披露したいだけなんだろ。 言い争いになってもいつも相手の真意からズレたところを叩いて自分の話に持って行く。
だから相手するのは無駄 相手にした時点で負けー
よう負け犬
涙拭けよw
面白くない
SSEでアルファブレンドは出来る?
ほー
まあ8bitのアルファブレンドで「256で割る」ってのは間違いなんだけどな。 正しい計算は「255で割る」
255の割り算は遅いじゃんw 257かけて上位ワードを取るとかすれば多少速いかな? 実用上256(8ビットシフト)で充分だけど。
十分じゃないだろw
グラボにやらせるのが最速
>>255 256で割るように改変した数式で、どのケースで誤差がでるか考えてみればいい。
誤差がでるやつだけ特殊化すればいいだけでは?w
677 :
255 :2009/02/23(月) 00:14:28
今更そんなこと言われても困るんだが
壮大に589した
いい流れだ
1足してから割ってみるとか。
駱駝の遺産分けの話か?
それじゃ、残ったビットは私が引き取りましょう。
dst.c = ((src.c - dst.c) * src.a >> 8) + dst.r; 254 = ((255 - 0) * 255 >> 8) + 0;
((v + 1) * 257) >> 16でおk これで確認 #/usr/bin/ruby (255*255).times{|i| if (((i+1)*257) >> 16) != (i / 255) puts "#{i} : #{i/255}" end }
問題は四捨五入をどうするかだな。 常に切り捨てなら685の式+pmulhwで8並列で処理できるが。
GPGPUがある時代に
GPGPU(笑)
OpenCLにワクテカ
なんか、結果が16bitでおさまr
>>691 pmulhw(v + 1, 257)なら32ビットの上位16ビットを取り出せるだろ。
ここは何年前のスレだw
>>692 だがPMULHUWはMMXではなくSSEの範疇なのであった。まあ、今更大した問題じゃないが
LZCNTってK10にあるけど Core2にはないよね?
LZCNTすら組み込み関数で用意してるVC++におどろいた
>>695 もともとビットスキャン命令があるからね。
SSE的にはcvtdq2psで浮動小数に変換して指数部をとれば並列処理できるぜ。
>>697 具体的にCore2だとどれ使えばいいのですかね?
movntss [mem], xmm0の代用方法 movd eax, xmm0 movnti [mem], eax movntsd [mem], xmm0の代用方法 movq mm0, xmm0 movntq [mem], mm0 emms そう考えればなくて困る命令は特にないな。 insertq/extrqは有効な使い道がわからん。 SSE4Aって誰得?
あと、全部0のときの動作が違うか
AMD String Libraryみたいなのって Intel出してないの?
SSE4.2対応のXMLパーザとか出してるでしょ。 有料だけど。
IntelのページにIntrinsics Guide for Intel(R) AVXって資料があったんで早速落としてみた。 exe形式になってるんだがダブルクリックしても prease waite...ってメッセージが出たまま起動しない。 なぜ〜? ハッ、まさかCPUがAMD製だから立ち上がらないのか?www
すんません。自己解決しました。 JRE最新にしたら立ち上がったわ。
Java入れてる?
706 名前:,,・´∀`・,,)っ-○◎●[sage] 投稿日:2009/04/04(土) 02:10:29 Java入れてる?
これ、もっとJava入れたらどうっすか?
Javaが足りないね
もっとJavaJava入れろ
ガバガバになっちゃうだろ
なんでjreってマイナーバージョン毎にディレクトリ掘るの? 05, 06, 07とか要らないんだが
お前が要るか要らないかは社会にとって微塵も重要ではないから。
なんで団子って頼まれもしないのに 2chに書き込むの?
715 :
,,・´∀`・,,)っ-○◎● :2009/04/04(土) 16:59:39
お前は頼まれて2chに書き込んでるのか
朝日に
JNI経由でSSEってネタかと思ったけど、違ったみたいだ。
昔書いたことあるよ
はいはい
いいえいいえ
団子の種類が変わった! どういう基準で変えてんの?
INTELのマニュアルってSSEだけとかわかれてないのかぁ どっかにまとまったやつないのかな
>>723 ありがとうー
あとでじっくり読んでみる
全部SIMDでやることが能じゃないぜ。
>575 そのMUX間違ってませんか?
OR ≠ "|"
はつみみです
お前はvoidかっ!?
void氏がバカをいじっているときは いじられ対象と同じくバカの壁を越えられない奴が釣られてくるので面白い。
ちなみに正解は (~A & C) | (B & C) だな OR が | であって || でないことくらいわかってるだろ つか、MMXからあるPANDN命令って3命令でMUX演算するのを想定してると思うんだが (V)PCMOVとかあったら使う頻度少なくならね? んで、今度はNANDとかNORが欲しくなる。 なんでこうビット論理演算に関して不自由な命令セットなんだろうな
(A & ~C) | (B & C) orz
こやつめ
735 :
デフォルトの名無しさん :2009/06/20(土) 18:45:25
SSEを使って乱数の生成を高速化する方法を教えてください
736 :
デフォルトの名無しさん :2009/06/25(木) 14:25:18
初心者で的外れな質問かもしれませんがSSEはどのように使うものなのですか? 例えば1+2をfor文で100個*100回やるとして、1度に10回計算できるから10個*100回で済むとかいうことですか? また、それを使うコードなどがあるのですか? それと、ヘッダファイルにあるライブラリの関数などにも適用できますか?
複数の計算を同時に行うことにも使うし、キャッシュを意識した データの取り扱いにも使う。 まぁここに聞く前にインテルのドキュメントでも見ておいたら?
インテルC++コンパイラ使うと自動的にSSEに最適化したコードで書き直されるの?
M$のVCでも四則演算にSSE2使ってくれるよ
じゃあ今までやってたコンパイルも勝手にSSEに対応してたの?そういう設定があるの?
/arch:SSE2 XMMレジスタを使うようになるだけで、ベクトル化はほとんどやらないから パフォーマンスがアップすることはまれ。逆に遅くなることも。
ほとんど? 全くの誤りじゃなくて?
VCはまったくやらないな。 意地でもやらないって幹事。
C/C++プログラマにはVisual StudioでPro以上なんて意味ないのでStandard買って 差額でICC買うと幸せになれます
ICCってフリーじゃないの? Linux版だけ?
wが多いのが好きならVIP(・∀・)カエレ!
だんごやさんだよwwwwww
やってみた /arch:sse2 sinとかcosはsseに変えてくれてた データ転送だけのwhileforは変えてくれないんだね そこはインラインか
intelのコンパイラって8万もするのか 高すぎてかえないお
SSE2にはsin cosはないおw
まあ、浮動小数点数のSSE2処理は別に高速化のためじゃなくてx87 FPU捨てるためのもんだし
x87捨てれないって SSE2が持ってるのは四則演算とシャッフル演算とベクトル演算程度だろ 超越関数は相変わらずFPUに頼るしかない
マイクロコード実装のFPU超越関数命令使うより、 四則演算で書かかれた超越関数サブルーチンを使った方が速い。 intelのコンパイラなんて、SSE2未対応CPU向けコードでも fsin命令は使わず四則演算で計算してる。
超越至極にございます。
vc6.0いっつも使ってるけど sse2使おうとして /arch:sse2にして2008expressに変えて コンパイルリンクしたら 同じ動作しない/(^o^)\ナンテコッタイ voidつけろ系のワーニングは無視して やったけどさ 結構仕様変わってるんだね ちなみに自分で作ったfftだけ/arch:sse2 にしてfft10000回やってみたら2秒縮まったお けっこうぎゃく汗したらxmm系結構使ってるみたいで がんばってるんだね そこだけ そのまま持って行って同じ動作しないのは めんどいな vc6.0のままインライン+fftだけ2008のでコンパイルするか。 できるかわからんけど
日記はお前の部屋の壁にでもかいとけ
>>758 うっせーな
なんで同じ動作しないかとかわかる?
最近覚え始めたんだけどこれってレジスタ単独のアンパックって 一発で出来ないのかな? 本来のアンパックって言っていいのかわからないけど 998877を009900880077みたいに広げるの
SSE4.1を使えばできるyo PMOVZXBW xmm, xmm/m64 PMOVZXBD xmm, xmm/m32 PMOVZXBQ xmm, xmm/m16 PMOVZXWD xmm, xmm/m64 PMOVZXWQ xmm, xmm/m32 PMOVZXDQ xmm, xmm/m64
>>761 うわっこりゃニーモニックを覚えるだけで一苦労だ
4.1なのかぁありがと しかし規則的だとはいえ命令も長くなってきて ぱっと見ランダムな文字列に見える
Packed MOVe with Zero eXtension, Byto to Word
比較命令でワード4ついっぺんに比較出来て喜んでいたんだけど その結果で分岐させるにはどういう方法がスマートなんだろう 比較の結果がこうだったらこっちとかやりたいんだけど 結果が入ったMMXレジスタをどう扱ったらいいかわからない
あーPMOVMSKBなんてのがあるんだ失礼しました
SSE系の命令セットって、あとは超越関数が入れば一昔前のGPUの命令セットと 大して変わらなくなるな。
MMXのみでやってるんだがパックド整数の除算をどうしたらいいのかわからん
逆数をかける
定数による除算はシフト等で置換できる 2^nならシフトのみでいける x/y≒x*(2^n/y)>>n あきらめてSSEにでも
つか、いまさらSSEが使えないCPUとか使ってるのか?
やばいまったくわからない 逆数求めるところから既にわからん… なんか手持ちの色んなソフト見てみたらみんなMMX以降みたいなのばっかだったから とりあえずMMXでやってみたんだ
ごめん出来た よーく見たら割る値が256だけでいけることに今気が付いた…
実は32bit画像同士の合成をMMXでやろうと思って作っていたんだけど cで何も考えず乗算除算使いまくった素のプログラムより遅くなったw なぜなんだああああああ
( ^ω^)...
下手にMMX使うよりSSEのprefetch命令使った方がよっぽど手軽にしかも速くなるんだよな
2箇所作ってたんだけどたくさんループさせてた片方がcのままだった で、そこもMMXにしたら確かに4倍近く速くなった気がする でも白を合成すると段々黒くなってくるなあ やっぱりアルファが255なのに256で割りまくってるのが駄目なんかな なかなか難しいね
で、また
>>669 あたりからの話題を繰り返すわけだな
あー上で全く同じことやってるんだな このスレためになるな しかし全く考えてなかったからレジスタが全然足りなくて困る 16本くらいにしてくれればよかったのに…
XMMレジスタ使えよ
でも話題の繰り返しになっちゃうかもしれないけど pmulhwで257掛けてどうのっていうの 小数点全部切り捨てだから意味なくない?
あ、これって固定小数点でやるってことなのか 今更気が付いた どのみち画面が真っ黒になって出来なかったけどw
1足すの忘れてたのを直したらちゃんと出来た
お前の実況スレでもなければ、日記帳でもない
MMXレジスタとXMMレジスタとあるみたいなんですが、 32ビットCPUだとそれぞれ別個に8個ずつあるんですか? 違いはMMXが64ビットでXMMが128ビットというだけ?
ggrks
散々ググったけどわからんかった。
IntelかAMDのサイトからPDF落として読めよ 常識だぞ
Intelのマニュアルはあるけど、何ページを読んでいいのかわからない。 日本語ならなんとか探せるとは思うんだけど…
Intel Architecture Software Developer's Manual Vol.1の CHAPTER9〜11を読め 英語が分からないとかそういう質問は受け付けない
ありがとう。 …80ページくらいあるな… The eight 128-bit XMM data registers...(中略)... they can be accessed independently from the x87 FPU and MMX registers and the general-purpose registers ってあるから、一つ目の質問の答えはyes? 二つ目の答えはよく読まないとわからないか。
Core2とかi7は16個のXMMだったような・・・ PDFは常に最新版を
MMXが64ビットというのはあってる SSEが単精度、SSE2から倍精度の浮動小数点を扱える(XMM)
MMXレジスタ: x87 FPUスタックと共用 XMMレジスタ: 新規追加
796 :
デフォルトの名無しさん :2009/09/30(水) 20:18:04
進化したな
日本語版ドキュメント一気にSSE4.2までカバーされたな まあ、訳がどこそこおかしいが。 一時期日本Intelの仕事サボり具合は異常と思った。
なに、仕事しているのか。 ダウンロードしてみよう。
俺が訳したほうがまし
流れ割ってすいません。 今PCMのステレオをモノラルに変換するコードを書いているのですが 下の処理をSSE2で書き換える場合どうすればいいでしょうか? pshufw mm0, mm1, 0xDD
xmm1にmm1の2つ分のデータが入ってると仮定して pshuflw xmm0, xmm1, 0xDD pshufhw xmm0, xmm1, 0xDD
>>801 助言のほうありがとうございます。
参考に色々試したら解決しました。
>>797 人間あれが普通。
むしろ日本人が異常。
本家が最新命令セット発表するたびに都度ドキュメント出してるわけだからさ。 その異常な日本人がサボってるって話をしてるんでしょ。
SSE2までの命令で倍精度浮動小数点を丸めモードに関わらず切り捨てで64ビット整数にするのって32ビットじゃ無理?
32ビット整数じゃなくて64ビット整数じゃないと駄目なのか? CVTTPD2DQで十分じゃん どのみち指数部が±2^63で扱える範囲超えてたら死ぬんだぜ それ以上欲しかったらビットフィールド自力で展開しろとしか。
MMXでパックワードの上位ビットをマスクしたいのですが、 通常は下記の様にやると思いますが、 MMXレジスタ(mm1)を使わずにmm0のみでやる代替法はないでしょうか。 mov eax, 0x00FF00FF movd mm1, eax punpckldq mm1, mm1 pand mm0, mm1
pand mm0.[sdi] とか
psllw mm0, 8 psrlw mm0, 8
>>808 の補足だけど0x00FF00FF00FF00FFをデータセクションに置いて
pandの第2オペランドをそのアドレスにする
>>808 >>809 >>810 お応えありがとうございます。
それら以外はないでしょうか?汎用レジスタも使いたくなくて、
シフト二回はpand一回に比べて処理が多くなってしまうので、
1つの命令で済ませられるような…難しいとは思うのですが。
808のでいいじゃないか。 汎用レジスタ使わなくても書けるでしょ?
sdiなんてレジスタないけどな
ところで何で今更MMXなんだぜ?
>>813 ほんとだーボケてんな、俺
esiとかediとかebpな
pand mm0,[esi+16]っていう書き方もできるし、ほとんど即値を使えないmmxでは
データセクションに定数を置いて参照するのは常套手段なんでは?
> 1つの命令で済ませられるような
インテルに作ってもらえば良いじゃん!
あとC/C++のインラインアセンブラで使う場合は、定数はC側から定義すると思うが static constで定義しる
すみません、レス遅くなりました。
>>815 の[esi+16]とかのやり方が良さそうです。
1つのレジスタで色々と使い回しが利きそうで。
ご丁寧に教えて下さり、ありがとうございました。
Bulldozerにはがっかりだ。
why?
調べてみればみるほどBulldozerの設計は理にかなってるけどな。 ま、FPUの実装はさすがに旧SSE5を引きずってるのでSandy BridgeのAVXユニットと比べたら見劣り感はあるが L1データキャッシュとロード・ストアユニットが1つのモジュールに2セットある意味を考えてみればいい。 1つのL1キャッシュで帯域倍増・LSU倍増よりは無理が無い。
>>819 2コアでSSE共有じゃシングルスレッドのをマルチスレッドで実行しても今より性能性能伸びないし、
別コアで今どのユニットが使用中か予測しようがないじゃないから
CodeAnalyst Performance Analyzerで解析も無理じゃないか?
節約した分クロック上がってコア数も増えることを祈ります。
2コアあたり 2FMA と、1コアあたり 1MUL1ADD って変わらないじゃん それより L2 直結でバス幅128のままなのかどうかが気になる
変わらないどころか乗算と加減算が結合できるケースでしか2倍の性能を発揮できない
実際のユニット構成は多分 2MUL2ADD なんじゃないの
仕様調べてないけどFMAの精度ってどうなのさ。 MULとADDに分けちゃうと精度落ちない?
>>825 流石にそれはない。
FMACとは別にPermuteユニットがあって合計4ユニットかな
>>826 それは実装次第。そもそもFMA演算はIEEE754準拠じゃないんだよな。
加算のデノーマライズをパイプラインに隠蔽できるので、トータルのレイテンシが短くなると。
演算ユニットレベルで積和を統合する最大のメリットは、積和演算のレイテンシが短くなること
乗算:denormalize→乗算→normalize
加算:denormalize→加算→normalize
積和算:denormalize→乗算+加算→normalize
しかも乗算ユニットに加算機能を付けるだけで対応できるので乗算・加算器を別々に持つよりは
実装コストが低い。
デメリットは
>>824
つIEEE 754-2008
ああ2008にはFMAはあるね
830 :
デフォルトの名無しさん :2009/12/23(水) 18:49:50
あるね
831 :
デフォルトの名無しさん :2010/01/01(金) 20:27:45
直リンはやめろ
hを抜いてるから直リンではないという屁理屈
>>831 なんかこのコード変じゃないか?
__m64 m64Color1;
__m64 m64Color2;
m64Color1 = _mm_unpacklo_pi8(_mm_cvtsi32_si64(Color1), _mm_setzero_si64());
m64Color2 = _mm_unpacklo_pi8(_mm_cvtsi32_si64(Color2), _mm_setzero_si64());
m64Color1 = _mm_mullo_pi16(m64Color1, m64Color2);
m64Color2 = _mm_srli_pi16(m64Color1, 8);
m64Color1 = _mm_adds_pu16(m64Color1, m64Color2);
m64Color1 = _mm_adds_pu16(m64Color1, _mm_set1_pi16(0x0001));
m64Color1 = _mm_srli_pi16(m64Color1, 8);
m64Color1 = _mm_packs_pu16(m64Color1, _mm_setzero_si64());
return (DWORD)_mm_cvtsi64_si32(m64Color1) & 0x00ffffff;
255で正規化された2値の乗算らしいけど
これだと((a*b)+(a*b)/256+1)/256という計算になって無駄が多いと思う
835 :
デフォルトの名無しさん :2010/01/03(日) 23:44:06
>これだと((a*b)+(a*b)/256+1)/256という計算になって無駄が多いと思う a*bは16ビットで、これに>684のように257をかけるのはMMXでは無理 MMXでこれ以上の方法は思いつかない たしかSSE3で32ビット乗算が使えるはず レジスタの使い方は改善の余地があるんじゃないかな
作者の結果↓ Multiply colors (C = C1 * C2) Normal 1.7752063 sec Table 1.2520575 sec MMX 1.0862872 sec SSE2 0.5878748 sec コード見た感じだとSSE2はMMXのただの128bits拡張のようだ その割にはSSE2速すぎるだろ 実行ファイル用意されてないから何とも言えないけど
多分計った後でSSE2版が無意味なことに気づいて 脳内でタイム半分にしたんじゃないの
命令列が不明だから、議論するだけ無駄。
作者はC2D使ってるからx87やMMXのレジスタよりXMMの方が速いはず だから多分そのタイムであってる
手元のC2DP8600でVS2008のGUIからリリースビルドしたら似たようなタイムになることを確認 Multiply colors (C = C1 * C2) Normal 1.6820140 sec Table 1.1875109 sec MMX 1.0300781 sec SSE2 0.5574127 sec
842 :
デフォルトの名無しさん :2010/02/16(火) 11:00:55
SSEってもっと速くならないのか?
>>831 のような単純な処理でこの程度の速度じゃあ
843 :
デフォルトの名無しさん :2010/02/16(火) 13:11:15
>>842 XMMレジスタの大きさの16バイトずつで処理すればもっと速くなるよ。
個人のシェアウェア作者だけど もうpen3以前のcpuは切り捨ててsse2使ってもいい頃かな? いっそssse3でもいいか
個人的にはSSE3までにしておいてもらいたい。どうしても処理を間に合わせるために アセンブリ言語で書かねばならないような状況でないかぎり。 SSEを使った処理を自分では書かず、コンパイラに最適化オプションを指定してやる程度の 自己満足目的なら、SSSE3使う意味があるとは思えない。
haddってssse3じゃね?
SSE3だよ
中古パソコン市場ではまだPen4世代も多いからSSE2までにしといた方が
せっかくwindowsで互換性あるのに、intelのハード機能使っちゃうと寿命が短いプログラムになっちゃうよ。 それを承知でやるならいいけど、高速化とかならが目的ならgpu(当然2004-6年ごろ以降のPC)に任せるべき。 どうしてもsseがいいならamd64からsse2が最低ラインか。
x64でもSSE3が使えないCPUは見捨てていいと思うぜ
SSE2の次の区切りはAVXな予感。
普通はsse2じゃなくてsseが一区切りだと思うよ。sseハードユニット的に。
x86-64で絶対使えるという点でSSE2も区切りとしてはいいと思う。
32bits osは後10年は当然にもつけど、そのプログラムは10年も持たないだろうから、sse1でいいと思うよ。 機能は少ないからといって主ターゲットが32bits osなのにsse2以降も考えてるなら、それほどsseに依存したプログラムであるならそもそもそのようなソフトに汎用性はない考えるといいだろう。
PhotoshopがSSE2が使えるかどうかのチェックやってるから、SSE2あたりが下限じゃね? まあ一応拡張命令が使えないCPU向けのパスは用意しておくべきかと。
ちなみにAVX世代ではNASMはバグ多すぎて使い物にならんかったり。 命令列に対するアラインメントの計算がどこそこおかしい。
おお、団子だ 久々だw お奨めのララビーはバッコンバッコンなっちゃったよね。 sseはずいぶん遠ざかって気が向いたらsseに戻らずopenglの方に行く予定だけど、団子はgpuの方はやらないの?
Pen3は古すぎるだろ。 それよりSSE2が使えないくせに息が無駄に長かったAthlonXPをサポートするかどうかだと思うんだ。
もっと大事なのは、計算が重いかどうかだ。 SSE使わなくても快適に動くならサポートすればいいし、 SSE4.2が無いと重くて仕方が無いのにPen4とかサポートする必要は無い。
sse4とかの世代だとpcの方がgpu持ってるからintel,amdに無駄に時間をかけずopengl(directx)+gpuかなって思う。 sseは結局、gpu generic programingが普及してなかった当時のpc向けのアクセラ・ユニットかな。俺の中では。 そのpc当時の性能だと、エンコーダソフトぐらいしかsseの活用は思い浮かばない。
861 :
844 :2010/03/03(水) 22:00:48
core2quadの1スレッドで、sse2で80%up、ssse3で130%up そんなソフトです ソフト名は控えさせていただきます
その差が大きいならサポートすればいいし、たいしたホットスポットで無いならsse(sse1すら)も不要かもな。 ここでいうsseとは、まばたき以下の時間つまり100マイクロ秒の性能を競う世界。
SSEが使えないようなCPUは絶対的な性能不足
VmwareやVirtualPCでサポートされていれば良いんじゃないカナ
新しいの使うのと古いの切り捨てるのは別の問題だという 当たり前のことを指摘してるのが団子しかいない あとの全員は使うか使わないかという論点で話をしてる
自演乙
>>861 もうSSE2まで使うモード、SSSE3まで使うモード両方実装しておけばいいよ。
起動時にCPUの種類によってどっち使うか決める。
868 :
844 :2010/03/03(水) 22:39:32
>>865 87fpuとsseで結果が異なると困るんです
ieee準拠で53ビット切り捨て等で技術的には可能なのはわかっているんですが
検証に手間と時間がかかりすぎます
>>865 え、そんなの当たり前過ぎて言っていないだけなんだが。
SSSE3 に fp 命令なんかあったっけ? そもそも fp って結果がぴったり一致しないと困るものに使うもんじゃないよね x87 か sse かというだけじゃなく、計算順とかでも変わっちゃうんだよ?
DirectXスレとC/C++スレでも最近こんな流れ見たな
ヒント ieeeのfpのビットの挙動を使ったコード
コードの蓄積があるなら全部サポートしとけよ 動く物をわざわざ動かなくする必要なんて無い
>>872 pshufb使って仮数部の切り捨てとか?
ねえねえいつから団子がこんなまともなこと言うようになったの? 最新ハード通り越して未発売ハードしかサポートしませんみたいな勢いの新製品厨だったのに
俺にはいつも通りの団子にしか見えないわけだが。 おたくの認識が間違ってただけなんじゃね?
団子さん団子さん 自演するなら名無しの方がいいですよ
つーかダンゴでも誰でもいいから、 SIMD対応のテンプレート行列ライブラリ作れや 対応はSSE2まででいいや サイズは4x4 matrixまででいいや 逆行列は必ずいれろ はやくしろカス
あとインラインアセンブラは使うな オール組み込み関数にしろ プリフェチ使え サンプルで、速度比較出来るベンチつけろ 当然フリーだ さっさとやれクズ
それすら自作できないならこの世界は諦めたほうがいいよ
>>881 お前が自作ライブラリによるベンチ結果でもUPしたら
話を聞いてやってもいいよ
ちなみにライブラリはC++版なら持ってるよ
SIMD版は優先順位が低いから・・
883 :
デフォルトの名無しさん :2010/03/04(木) 21:40:16
884 :
デフォルトの名無しさん :2010/03/04(木) 21:44:09
というかそれこそGPGPUの出番だろ
SSE2を使うとプログラムが早くなると勘違いしている馬鹿がいると聞いて
>>886 Intel様やSONY様は
4倍速くなると豪語してたし
>>879 C++なんてJava並に遅いものを使ってる時点で諦めろカス
絶対にどこかでアセンブラは使うんだって… 無茶言わんでくれ
あのさ、ものっそ基本的なことだけど たとえばHogeって関数を古いCPUから新しいCPUの機能までフルに使えるようにするのって HogeC HogeMMX HogeSSE HogeSSE2 HogeSSSE3 HogeSSE41 HogeAVX みたいな感じでカーネルコードをCPU機能レベル毎に作っておいて 初期化するときに関数ポインタセットするだけだろ C++がJavaなみに遅いとか言ってる奴は仮想関数とかRTTIとか使ってる法則。 もしくはSTLのアロケータも自作しない。 てかベターCとして使うなら十分C++は速いよ
Hoge3DNow・・
ベター C として使うなら C より速くね? でも仮想関数くらいは使わせでくだしあ
例外やRTTI等無効にしないとCより遅い
最適化の話を抜きにすればコンパイル言語は同じ速度だと思ってた JavaはC++より遅いだろjk
コンパイル時に解決できる使い方(RTTIなし)なら 仮想関数を使っても速度は低下しない CふくめRTTIを自前実装でやろうとするなら やはり同じように速度は低下する 言語が悪いのではなく、プログラマが悪い みたいなことを誰かが言ってたような まあ最適化の話ならrestrictとかファンクタとか・・・
void proc(unsigned int *dst, unsigned int *src, int siz) { do{ unsigned char *d = (unsigned char *) dst++; unsigned char *s = (unsigned char *) src++; d[0] = d[1] = d[2] = s[0]/4 + s[1]/2 + s[2]/8; }while(--siz); } ↑をSIMD化で早くしてください。
>>897 CPUを言えよw
x86ならこのままが一番良さそうな気がする。
どうしてもSIMD化したければ単精度に変換して逆数掛けるのが近道じゃね?
MMX/SSE2は糞だからエレメント毎に別のシフト量って命令は無い。
と、これ系のスレで毎度だだをこねている無い物ねだりのレスは俺です。
グレースケールなら (s[0]*3+s[1]*5+s[2])/8 じゃないのか?
>>897 よーわからんフィルタだな。
mov ecx, siz;
mov esi, src;
mov edi, dst;
sub ecx, 4;
add edi, 2;
sar ecx, 2;
cmp ecx, 0;
jle TAIL;
LAST:
movq mm0, [esi+0];
movq mm1, [esi+1];
movq mm2, [esi+2];
add esi, 8;
psrab mm0, 2;
psrab mm1, 1;
psrab mm2, 3;
paddb mm0, mm1;
paddb mm0, mm2;
movq [edi], mm0;
add edi, 8;
dec ecx;
test ecx, ecx;
jnz HEAD;
TAIL:
先頭の 2 画素と末尾 2 画素 + 端数はPlain Cで作るように。
テストしてないので、動くかどうかは知らない。
ごめん。 sar ecx 2; は sar ecx 3; の間違い あと、 LAST: も HEAD: の間違い。
902 :
デフォルトの名無しさん :2010/03/15(月) 01:10:19
>>897 >void proc(unsigned int *dst, unsigned int *src, int siz)
>{
> do{
> unsigned char *d = (unsigned char *) dst++;
> unsigned char *s = (unsigned char *) src++;
> d[0] = d[1] = d[2] = s[0]/4 + s[1]/2 + s[2]/8;
> }while(--siz);
>}
このd[1], d[2]は次のイテレーションで上書きされるけど
意図した記述なの?
>>898 > CPUを言えよw
とりあえずCore Duoでお願いします。
>>899 適当にそれっぽい色になる数にしてみました。
公式がちゃんとあるんですね。
>>900 どうも想定してるのとは違うっぽい動作をするようです。
>>902 4バイトずつ加算されてくので上書きされないと思います。
904 :
898 :2010/03/15(月) 14:24:56
>>903 仕事ならライブラリを買いましょう。
人件費からすれば微々たる金額です。
趣味なら
>>898 をヒントに自分で頑張りましょう。
分からない所があったら書きかけのコードを添えてまた質問して下さい。
趣味だけどSIMDには興味がねーんだよボケと言うのなら
>>897 のままで結構です。
いやマジで。
演算量が少な過ぎてメモリアクセスの遅さを隠蔽出来ません。
prefetchとmovntiだけ使ってみるとか。
減ってく場合ハードウェアプリフェッチって効かないんだっけ?
d[3]変更不可縛りがきつくて、色々と無理。
>>904 SIMD化すれば簡単に2〜4倍高速化できると聞いて期待してたのですが、難しいですか。
わかりました。自分で頑張ってみます。
>>905 prefetchってよくわからないんです。
_mm_prefetch(src, _MM_HINT_NTA);
d[0] = d[1] = d[2] = s[0]/4 + s[1]/2 + s[2]/8;
これって無駄になりますよね?
_mm_prefetch(src+16, _MM_HINT_NTA);
d[0] = d[1] = d[2] = s[0]/4 + s[1]/2 + s[2]/8;
↑この場合ってprefetch命令で確保した分はs[0]へアクセスして自動的に引っ張ってきた分で
押し流されて無かったことになったりしませんか?
909 :
898 :2010/03/15(月) 19:28:57
>>906 効くよ。
>>908 単精度にせず愚直にSIMD化してみたけど10%速くなっただけ。(Core 2 Duo Merom)
prefetchはsrc+16なんて近くじゃなくてもっと遠くを指定した方が良い。
でもハードウェアプリフェッチが効くので殆ど意味はない。
あと、L2キャッシュにロードするんだから1MB以上はあるわけで、そうそう簡単には押し流されない。
d[3]を破壊しても良いなら、 mov edi, dst mov esi, src mov ecx, siz BEGIN_: prefetchnta [esi+512] mov eax, [esi] mov dl, [esi+2] shr al, 2 shr dl, 3 shr ah, 1 add al, dl add al, ah mov bl, al mov ah, al shl ebx, 16 mov bx, ax movnti [edi], ebx add esi, 4 add edi, 4 dec ecx jnz BEGIN_ sfence 多分こんな感じ。
x86はニーモニックが汚い割りには痒い所に手が届くような作りになってるよな
Core 2以上専用でいいならpmaddubsw/pshufb使えば速いんだが・・・
>>911 むしろ痒いところに手が届くよう、様々な種類の孫の手を用意した結果が今の86爺さん。
最近じゃ孫の手の改良に飽き足らず、人体改造で腕を6本生やし更に、一つの腕で孫の手を2本同時に使えるようにしちまったよ。
>>913 もうそれは奇形児と言っていいな
そういうCPUが主流なのも不思議だが
便利な事は便利だ
腕生やすときに「右だけでいっか、左あんまり使わないし」みたいなことをするのがイッテル
916 :
898 :2010/03/17(水) 00:19:14
>>912 アンパックと演算がいくら速くなった所で今回のボトルネックはメモリだろ。
ちょっとは変わるけどね siz=1024 9.01 c 4.62 asm 4.52 mmx2 2.92 ssse3 siz=65536 9.01 c 4.78 asm 3.89 mmx2 2.28 ssse3 siz=4194304 9.82 c 7.47 asm 5.07 mmx2 4.80 ssse3 単位はcycle/siz pmaddubsw って知らなかったんで使ってないけど、後でやってみよう
ハードウェアプリフェッチって、今アクセスしているアドレスの256バイト先のアドレスをとってこようとするんだよね。 一回に1キャッシュライン分だから、たとえば、Float A[10000]という配列があって、最初にA[0]をアクセスしたら、 A[0]〜A[16]までキャッシュにたまって、ちょっとしたらA[64]〜A[80]までがキャッシュされている。 それを繰り返して、A[960]以降をアクセスしたら、その256バイト先は4KBをまたぐので、 ハードウェアプリフェッチは機能しない。ということだよね? つまりソフトウェアプリフェッチを入入れるときは、遠くの方のアドレスを指定しておくのが有効だけど、 この例でA[960]、A[976]、A[992]、A[1008] あたりをプリフェッチで指定しておけばしてより効果的になるのかな?
リニアなアクセスにはあんまり効果ないんじゃない?
921 :
898 :2010/03/17(水) 08:38:57
>>920 917は団子じゃねーのかw
Cと他に差があり過ぎるしpmaddubswを知らないってどういうことかと思った。
917のcycle/sizってのはtotal clock÷sizでいいのか?
まるで全部キャッシュに入っているかのようなスピードなんだが。
dppsって遅くね? mulとhadd使ったほうが早いんだけど使い方が悪いんかな?
codepad.org/jXsRnZ1O codepadのgccがintrinsicsを持ってないようだからgccでコンパイルしてDにポートした。 alignがバグっていて無駄な時間を過ごしてしまった。 proc0は純粋な実装で参考程度。codepadだと遅いけど手元の測定では他と大きな違いはない。 それとDがSSSE3に対応していないようなのでコメントアウトしてある。これも手元の測定では他と然程変わらない。 最適化の余地は残っていると思うものの、時間が劇的に変わるとは思えない。 proc2, proc3はproc0とは計算方法が違うのでproc0とは異なる結果を出す事がある。
Complex Decoder Pathでデコードコストが大きいから連続で使っちゃ駄目。 だってさ、内部的に、乗算+シャッフル×2+加算+シャッフル×2+加算 に分解して実行してるだけだぜ? 適度に他のSimple Decoder Pathの命令と混ぜて配置すればスループット改善するかも
>>923 void proc3(unsigned int *dst, unsigned int *src, int siz)
だけど
> __m128i vSum = _mm_srli_epi32(_mm_add_epi32(vABS, vGRS), 8);
> __m128i vDst = _mm_shuffle_epi8(vSum, vSplat);
ここ8ビットシフトする必要なくね?
これでおk
__m128i vSplat = _mm_set_epi8(
0xff, 13, 13, 13,
0xff, 9, 9, 9,
0xff, 5, 5, 5,
0xff, 1, 1, 1);
あともう少し改善できるところがあるけどそもそもメモリネックだとか言う人が言うので
これ以上は突っ込まない
ヒント:pandはどのポートでも発行出来る
> (s[0] * 64 + s[1] * 128 + s[2] * 32) / 256 速度以前にグレイスケールの変換式として問題があるだろ
/) ///) /,.=゙''"/ / i f ,.r='"-‐'つ____ / / _,.-‐'~/⌒ ⌒\ / ,i ,二ニ⊃( ●). (●)\ / ノ il゙フ::::::⌒(__人__)⌒::::: \ ,イ「ト、 ,!,!| |r┬-| | / iトヾヽ_/ィ"\ `ー'´ /
確かに Y = ( 2 * R + 4 * G + B ) / 7で近似ならわかるけど8で割る意味が不明 正しい式は Y = ( 0.298912 * R + 0.586611 * G + 0.114478 * B )
グレースケールなん?
Y = ( 0.298912 * R + 0.586611 * G + 0.114478 * B ) これ256倍しとけ
>>924 え、Complex Decoder Pathを並べるとパイプライン詰まるの?
OoOしてくれるかと思ってた。
シフトはいらないね。
andはどこで使うんだろう。
>>931 うん、897に合わせて書いているけど931がすぐ発想し易いようにしてある。
本質的にはどれ使っても大した違いはないという事が言いたかっただけだから。
どうせ大したことない差だし0.25、0.5、0.125でもいいかな、と。 自分で書いてみましたが、SSE使っても最初のと速度変わらないままでした。
>>932 アウトオブオーダなのはデコード後であってデコーダの解釈は並べた順。
>>933 いや使い物にならないと思う
rgb 255 入れたとき w 221にしかならないじゃん
じゃ俺も貼るか、ループの中だけでいいよね
>>936 > rgb 255 入れたとき w 221にしかならないじゃん
え?それに何か問題でも?
白が灰色になっても困らないのか?
必要じゃなきゃ困らないだろ
おう遅くなった ; asm ; edi=dst+siz*4, esi=src+siz*4, ecx=-siz*4 .lp: mov al, [esi+ecx] mov bl, [esi+ecx+1] mov dl, [esi+ecx+2] shr al, 2 shr bl, 1 add al, bl shr dl, 3 add al, dl mov [edi+ecx], al mov [edi+ecx+1], al mov [edi+ecx+2], al add ecx, 4 jnz .lp
.lp: ; mmx2 edx=dst+siz*4, eax=src+siz*4, ecx=-siz*4, mm0=zero, mm7=factor movq mm1, [eax+ecx] movq mm2, mm1 punpcklbw mm1, mm0 punpckhbw mm2, mm0 %ifdef accurate pmaddwd mm1, mm7 pmaddwd mm2, mm7 pshufw mm4, mm1, 0b11111110 pshufw mm5, mm2, 0b11111110 paddw mm1, mm4 paddw mm2, mm5 pshufw mm1, mm1, 0b11000000 pshufw mm2, mm2, 0b11000000 psrlw mm1, 8 psrlw mm2, 8 %else pmulhuw mm1, mm7 pmulhuw mm2, mm7 pshufw mm4, mm1, 0b11001001 pshufw mm5, mm2, 0b11001001 paddw mm4, mm1 paddw mm5, mm2 pshufw mm1, mm1, 0b11010010 pshufw mm2, mm2, 0b11010010 paddw mm1, mm4 paddw mm2, mm5 %endif packuswb mm1, mm2 movntq [edx+ecx], mm1 add ecx, 8 jnz .lp
; ssse3 ; edx=dst+siz*4, eax=src+siz*4, ecx=-siz*4, xmm0=zero, xmm6=shuffle, xmm7=factor .lp: movdqa xmm1, [eax+ecx] movdqa xmm2, xmm1 punpcklbw xmm1, xmm0 punpckhbw xmm2, xmm0 %ifdef accurate pmaddwd xmm1, xmm7 pmaddwd xmm2, xmm7 phaddd xmm1, xmm2 %else pmulhuw xmm1, xmm7 pmulhuw xmm2, xmm7 phaddw xmm1, xmm2 phaddw xmm1, xmm2 %endif pshufb xmm1, xmm6 movntdq [edx+ecx], xmm1 add ecx, 16 jnz .lp
; ssse3 pmaddubsw ; edx=dst+siz*4, eax=src+siz*4, ecx=-siz*4, xmm5=mask, xmm6=shuffle, xmm7=factor .lp: movdqa xmm1, [ecx+eax] %ifdef accurate movdqa xmm2, xmm1 pand xmm2, xmm5 %else pand xmm1, xmm5 %endif pmaddubsw xmm1, xmm7 %ifdef accurate paddw xmm1, xmm1 paddw xmm1, xmm2 %else psrlw xmm1, 3 %endif phaddw xmm1, xmm1 pshufb xmm1, xmm6 movntdq [ecx+edx], xmm1 add ecx, byte 16 jnz .lp
;segment .data %ifdef accurate qFactorW: dqFactorW: dw 77,150,29,0,77,150,29,0 dqShufB: db 1,1,1,255,3,3,3,255,5,5,5,255,7,7,7,255 dqShufB159d: db 1,1,1,255,5,5,5,255,9,9,9,255,13,13,13,255 dqFactorB: db 38,75,14,0,38,75,14,0,38,75,14,0,38,75,14,0 dqMaskB: db 0ffh,0,0ffh,0,0ffh,0,0ffh,0,0ffh,0,0ffh,0,0ffh,0,0ffh,0, %else qFactorW: dqFactorW: dw 16384,32768,8192,0,16384,32768,8192,0 dqShufB: db 0,0,0,255,2,2,2,255,4,4,4,255,6,6,6,255 dqFactorB: db 2,4,1,0,2,4,1,0,2,4,1,0,2,4,1,0 dqMaskB: db 0fch,0feh,0f8h,0,0fch,0feh,0f8h,0,0fch,0feh,0f8h,0,0fch,0feh,0f8h,0 %endif
>>940 ssse3(
>>942 )の!accurateを試してみたけど
>>917 みたいな大きな差が現れないどころか、純粋なCのプログラムより若干遅いんだけど。
それはさすがにないはず なんか間違ってるんじゃない あと実は917のときより全部ちょっと速くなってる siz=1024 65536 4194304 // 45nm shift 4.08 4.44 7.50 gcc4 4.02 4.38 7.43 asm 3.98 3.87 5.08 mmx2 2.37 2.26 4.80 ssse3 2.36 2.27 4.78 ssse3_2 (pmaddubsw) // 65nm shift 4.02 4.44 5.77 asm 4.39 3.89 4.55 mmx2 3.94 3.29 4.46 ssse3 2.66 2.19 4.44 ssse3_2 (pmaddubsw) // 45nm accurate 4.73 4.90 7.35 asm 3.94 3.84 5.08 mmx2 2.36 2.26 4.80 ssse3 2.36 2.26 4.81 ssse3_2 (pmaddubsw) // 65nm accurate 4.82 4.93 6.08 asm 4.36 3.78 4.57 mmx2 2.82 2.34 4.49 ssse3 2.77 2.26 4.43 ssse3_2 (pmaddubsw) gcc4 は -mtuneを pentium-m 以前にしたら途端にまともなコードを吐くようになった
あ、! 見逃してた。accurate じゃない方ってこと? なら 65nm で L1 の中なら肉薄されるね L1 内でループ回したら負けるかも そういうセットアップだと、まず movnt を普通の mov にして それから phadd とか pshufb とかバラすといいのかな? 団子が詳しそうだけど
phaddはpermute×2 + paddに分解されるので遅いです>< ビットマスクしてpsadbw(乗算扱い)した方が速いよ。精度はさておき。
実はSSSE3を使えばpmaddubsw→pmaddwd→pshufbだけでできるんだな。 pmaddubswの第2引数 __m128i vGSMultipler1 = _mm_set_epi8( ScaleR, ScaleG, ScaleB, 0, ScaleR, ScaleG, ScaleB, 0, ScaleR, ScaleG, ScaleB, 0, ScaleR, ScaleG, ScaleB, 0 ); pmaddwdの第2引数 __m128i vGSMultipler2 = _mm_set_epi16(1, 1, 1, 1, 1, 1, 1, 1); pshufbの第2引数 __m128i vSplat = _mm_set_epi8( 0xff, 15, 15, 15, 0xff, 11, 11, 11, 0xff, 7, 7, 7, 0xff, 3, 3, 3);
いずれにしても乗算ネックなんで悩ましい。 どうせ乗算ネックなら精度的にはR, BとG, 0に分けてpmaddwdの方が良いと思う。
0BGR -> GBGRで ScaleGを分割して精度を1bit稼ぐのはどうだ
片方無駄なphaddより全1掛ける方がどう考えてもいいね ていうか手元の最新コードではそうなってた でもさすがにバイトの和は使えないと思う > 精度を1bit稼ぐ お、気づいてくれた?
953 :
951 :2010/03/20(土) 04:52:11
ScaleGが4bitだから、1bit増えても5bitにしかならないから ScaleGの精度だけ上げて pmaddwd時に小数点の位置を合わせたほうがいのか
SSEを使って最適化を進めて、「やった2倍だ3倍だ」と思っていたら、 複数のコアを使ったら殆ど変わらなくなった時って悲しくならねぇ?
メモリ帯域とりあうからな ただ、メモリ帯域取らない別のワーカースレッドを並列稼働させればいいし 4コア分の仕事を1コアで賄えるなら結果省エネになる。
>>954 マルチスレッドにしなきゃいかんし、4コアで別々にSSE使えるからもっと速くなるから
無駄ではないだろ
外部メモリ帯域がネックじゃなければね 共有キャッシュ上のデータをうまく使い回してDRAM帯域をセーブするテクニックが必要になるし なおかつそういう用途でしか使い物にならない。
958 :
951 :2010/03/20(土) 14:11:27
>>953 ScaleGじゃなくてScaleBだった
SIMD化そのものが無駄。 正確にはSIMDに合わせて、SISDのコードをSIMDに加工するのが無駄。 たまたま無理なくSIMDに出来るコードがあったらやる程度で十分。
SIMDを極めた人が言うなら説得力がある。 そう出なければ単なる負け惜しみ。 けど、SIMDを極めた人は最初からSIMDを意識して設計するんでない?
単純なコードだとコンパイラの最適化のほうが速いってこともあるよ
画像処理みたいなデータ並列度の高い処理で使わないのはただの無能
ところでなんで団子や
>>831 の
>>834 みたいに
_mm_xxx_yyyの形で書く人がいないんだろ
知り合いとかもみんな基本はC使ってるくせにアセンブラ使いたがるよね
まあ単に俺がアセンブラ嫌いなだけなんだけど
コンパイラが信用出来ない by x264の中の人
くれてない、かな
pmaddubsw は片方符号付で7bit精度しかないんだけど
943ではちょっと工夫して他と結果そろえてる
実は速度とかよりここがメインだったんだけどなぁ
こだわらないなら団子の言う3命令だけでもできると思うけど
ただ
>>949 は引数全部違うよね
>>964 たまにアセンブラすら信用できないこともあるけどな、特にNで始まるあれは。
致命的なバグ大杉。
>>965 ごめん書いてから気づいたけど誰も突っ込まないから放置してた。
本当はYASM使いだけど、Cコードはかなりテキトーに書いた。引数順序とかテキトー
x86->x64, SSE->AVXの移行考えるならIntrinsics形式の方が楽だと思う。
>>963 Cコンパイラがメモリ参照するコードばかり吐き出しよるとです。
VCで/arch:SSE2やるとmovdqaとかにアラインされてないアドレス渡すコード吐くことがあったな
>>952 >>943 で精度を1bit稼いでるのは気づいていなかった
>>943 は
((77*R + 150*G) + 29*B)
を
((38*R + 75*G) + 14*B)*2 +R +B
に変形しているけど
>>951 で書いたのはこの変形
(77*R+51*G) + (29*B+99*G)
>>969 なるほどねえ、そっちは俺が気づいてなかった
幅いっぱい使いきってるのが美しい
45nm 以降なら shufb 一発で済んで3命令得だし
65nm だと uop 数変わんないけど遅くはならないはず
そっちの方が断然いい
2005はもう捨てろ
6年かかったけどそろそろ次スレに行けそうだな もう3D Now!は要らないんじゃない?
つまりそれだけ需要がなかったか、あるいは、この技術を必要とするプログラマが少なかったということか。 まあ、全体としてはマイノリティだけどな。
>>957 メモリ帯域に対してSSEの処理が速すぎるんだよね。
しかもハードウェアプリフェッチが機能するようになってから、
余計メモリ帯域を消費するようになった。
メモリ転送レイテンシ以下で32bitや64bit変数を圧縮、展開を出来るアルゴリズムはないのかな?
多少圧縮展開で時間がかかっても並列化によって計算時間は相対的に下がるから、
メモリ帯域をセーブ出来ると思うんだけどな。
そんなにあまくないか。
むしろそのうちメモリバスにスクランブルかかるんじゃないの? レイテンシー増えるけど著作権のためよ♪by利権団体
なんかどこぞ団体はいいそうだね。 メモリ毎に保証料払えと。 ただPCIExpressとかは輻射の低減ため、 スクランブルが掛かっているけどね。
製品単位で取ってるから、多重請求になっちまう。
>>972 次の6年に備えて「SSE AVX XOP」でおk
初心者質問で悪いんだが 1.パイプラインの使用率を見る方法 2.どの程度まで使用率を上げられるものか 教えてくだされ
980 :
デフォルトの名無しさん :2010/05/24(月) 14:01:42
V V (´・ω・`) うさちゃんピース
>>975 マザボの大半は著作権フリーの台湾で作っているのでまずあり得ない