x86/x64 SIMD命令一覧表 (SSE~AVX2)
・・・なんでこんなことを調べているのでしょうか・・・
visual studio expressを2015にしたんですよ。
んで、よくよく調べるとMASMってちゃんとVCに入ってるんですね。
というわけで今までMASM6.15でアセンブルしていたのを最新版でアセンブルしようと・・・したらできなかったという話です。
masm6では問題なくアセンブルできていたのに、その後継の14でできなくなるとは之如何に。
table1 sword 16384, 21407, 16384, 8867というようなコードをアセンブルすると
movdqa xmm0,[table1]
エラー A2022 instruction operands must be the same size
と言われるという・・・
如何せん僕はwindowsのソフトをほとんど弄ったことがありません。
見たことがある(わかるわけではない)のも386のアセンブラぐらいというロートルなので、そもそもオペコードの意味が分からない・・・
とかいろいろグーグル先生に尋ねた結果、アドレスの書き方が良くない?らしいということが判明。
movdqa xmm0,xmmword ptr[table1]というようにしたら治りました。
まぁ、あまり原因はわかっていないのですが。
_DATA SEGMENT PARA PUBLIC USE32 'DATA'とか書いてあるのが多少気になりますが、そもそも意味が分からない・・・
という話とは多分関係ないのですが、ひとまず、DGIndexをAVX2を有効にしてコンパイルすると
同一ソースで150MB/s→170MB/s@Haswell4.5GHzぐらいになりました。fpsは調べてませんが。
大体1割早くなった感じでしょうか。
AVX2>AVX=SSE2ぐらいで。
TIVTCも早くなったりするだろうか。
というわけで試してみたけど変わりませんでした。
そして別にコンパイラ最適かじゃなくて、Tdecimateの差分算出を並列処理させれば早くなるんじゃね?とか思って
ベクター化と並列化のメッセージ
を眺めている今日この頃。
深みにはまるだけな気がして仕方がない・・・
そして丸2日かけてコードを最適化した結果、前提条件が間違っていることが判明した。
時間がかかっているのはそこじゃなかった、という・・・
結局のところネックはメモリアクセスっぽいので、演算を並列化しても早くならないっぽい、という・・・多少疑問もありますが。
アクセス順を調整すればあるいは・・・いや、コンパイラ最適化かけてるからどうしようもないのか・・・?
よくわかりません。
後々のために参考になったサイトは下記
プログラミング言語 C の新機能 配列
OpenMPの使い方
ループの独立性
いや、結構頑張ったんですよ?
というのを__asm { mov y, 2 yloop0: mov ecx, y0a mov edx, y1a cmp ecx, edx je xloop_pre0 mov eax, y cmp eax, ecx jl xloop_pre0 cmp eax, edx jle end_yloop0 xloop_pre0: mov esi, incl mov ebx, startx mov edi, mapp mov edx, mapn mov ecx, stopx xloop0: movzx eax, BYTE PTR [edi+ebx] shl eax, 3 add al, BYTE PTR [edx+ebx] jnz b10 add ebx, esi cmp ebx, ecx jl xloop0 jmp end_yloop0 b10: mov edx, curf mov edi, curpf movzx ecx, BYTE PTR[edx+ebx] movzx esi, BYTE PTR[edi+ebx] shl ecx, 2 mov edx, curnf add ecx, esi mov edi, prvpf movzx esi, BYTE PTR[edx+ebx] movzx edx, BYTE PTR[edi+ebx] add ecx, esi mov edi, prvnf movzx esi, BYTE PTR[edi+ebx] add edx, esi mov edi, edx add edx, edx sub edi, ecx add edx, edi jge b30 neg edx b30: cmp edx, 23 jle p30 test eax, 9 jz p10 add accumPc, edx p10: cmp edx, 42 jle p30 test eax, 18 jz p20 add accumPm, edx p20: test eax, 36 jz p30 add accumPml, edx p30: mov edi, nxtpf mov esi, nxtnf movzx edx, BYTE PTR[edi+ebx] movzx edi, BYTE PTR[esi+ebx] add edx, edi mov esi, edx add edx, edx sub esi, ecx add edx, esi jge b20 neg edx b20: cmp edx, 23 jle p60 test eax, 9 jz p40 add accumNc, edx p40: cmp edx, 42 jle p60 test eax, 18 jz p50 add accumNm, edx p50: test eax, 36 jz p60 add accumNml, edx p60: test eax, 56 jz p120 mov ecx, prvpf mov edi, prvppf movzx edx, BYTE PTR [ecx+ebx] movzx esi, BYTE PTR [edi+ebx] shl edx, 2 mov ecx, prvnf add edx, esi mov edi, curpf movzx esi, BYTE PTR [ecx+ebx] movzx ecx, BYTE PTR [edi+ebx] add edx, esi mov edi, curf movzx esi, BYTE PTR [edi+ebx] add ecx, esi mov edi, ecx add ecx, ecx add ecx, edi sub edx, ecx jge b40 neg edx b40: cmp edx, 23 jle p90 test eax, 8 jz p70 add accumPc, edx p70: cmp edx, 42 jle p90 test eax, 16 jz p80 add accumPm, edx p80: test eax, 32 jz p90 add accumPml, edx p90: mov edi, nxtpf mov esi, nxtppf movzx edx, BYTE PTR [edi+ebx] movzx edi, BYTE PTR [esi+ebx] shl edx, 2 mov esi, nxtnf add edx, edi movzx edi, BYTE PTR [esi+ebx] add edx, edi sub edx, ecx jge b50 neg edx b50: cmp edx, 23 jle p120 test eax, 8 jz p100 add accumNc, edx p100: cmp edx, 42 jle p120 test eax, 16 jz p110 add accumNm, edx p110: test eax, 32 jz p120 add accumNml, edx p120: mov esi, incl mov ecx, stopx mov edi, mapp add ebx, esi mov edx, mapn cmp ebx, ecx jl xloop0 end_yloop0: mov esi, Height mov eax, prvf_pitch mov ebx, curf_pitch mov ecx, nxtf_pitch mov edi, map_pitch sub esi, 2 add y, 2 add mapp, edi add prvpf, eax add curpf, ebx add prvnf, eax add curf, ebx add nxtpf, ecx add prvppf, eax add curnf, ebx add nxtnf, ecx add mapn, edi add nxtppf, ecx cmp y, esi jl yloop0 } }
{ int xsize = (stopx - startx) / incl; //#pragma omp parallel for //for (y = 2; y < Height - 2; y += 2){} for (int jj = 1; jj < Height / 2 - 1; ++jj){ y = jj * 2;// if ((y0a == y1a) || (y < y0a) || (y > y1a)){ //for (int ebx = startx; ebx < stopx; ebx += incl){} for (int ii = 0; ii < xsize; ++ii){ unsigned char eax; int edx,ebx; ebx = startx + ii*incl; eax = ((*(mapp + ebx)) << 3) + (*(mapn + ebx)); if (eax != 0){ edx = (*(prvpf + ebx) + *(prvnf + ebx)) * 3 - ((*(curf + ebx) << 2) + *(curpf + ebx) + *(curnf + ebx)); if (edx < 0){ edx = -edx; } //b30 if (edx > 23){ //else p30 if ((eax & 9) != 0){accumPc += edx;} //p10 if (edx > 42){ //else p30 if ((eax & 18) != 0){accumPm += edx;} //p20 if ((eax & 36) != 0){ accumPml += edx; } } } //p30 edx = (*(nxtpf + ebx) + *(nxtnf + ebx)) * 3 - ((*(curf + ebx) << 2) + *(curpf + ebx) + *(curnf + ebx)); if (edx < 0){ edx = -edx; } //b20 if (edx > 23){ //else p60 if ((eax & 9) != 0){ accumNc += edx; } //p40 if (edx > 42){ //else p60 if ((eax & 18) != 0){ accumNm += edx; } //p50 if ((eax & 36) != 0){ accumNml += edx; } } } //p60 if ((eax & 56) != 0){ //else p120 edx = (*(prvpf + ebx) << 2) + *(prvppf + ebx) + *(prvnf + ebx) - (*(curpf + ebx) + *(curf + ebx)) * 3; if (edx < 0){ edx = -edx; } //b40 if (edx > 23){ //else p90 if ((eax & 8) != 0){ accumPc += edx; } //p70 if (edx > 42){//else p90 if ((eax & 16) != 0){ accumPm += edx; } //p80 if ((eax & 32) != 0){ accumPml += edx; } } } //p90 edx = (*(nxtpf + ebx) << 2) + *(nxtppf + ebx) + *(nxtnf + ebx) - (*(curpf + ebx) + *(curf + ebx)) * 3; if (edx < 0){ edx = -edx; } //b50 if (edx > 23){ //else p120 if ((eax & 8) != 0){ accumNc += edx; } //p100 if (edx > 42){ //else p120 if ((eax & 16) != 0){ accumNm += edx; } //p110 if ((eax & 32) != 0){ accumNml += edx; } } } } //p120 } } } mapp += map_pitch; mapn += map_pitch; prvpf += prvf_pitch; prvnf += prvf_pitch; prvppf += prvf_pitch; curpf += curf_pitch; curnf += curf_pitch; curf += curf_pitch; nxtpf += nxtf_pitch; nxtnf += nxtf_pitch; nxtppf += nxtf_pitch; }
というように解読して、その後C言語でパラ化。
・・・まではしたのですが・・・ね。
0 件のコメント:
コメントを投稿