2017-02-09 11 views
0

これはこれに続きますpostです。免責事項:私はプロファイリングをゼロにしており、アプリケーションを持っていなくても、純粋にベクトル化の詳細を学ぶことができます。自動ベクトル化配列比較関数の使い方

私のコードは以下の通りです。私はi3 m370を搭載したマシンでgcc 4.9.4をコンパイルしています。最初のループは、私が期待するようにベクトル化します。しかし、tempの各要素をチェックする2番目のループは、すべての "andb"命令で、ベクトル化されたAFAICTではありません。私はそれが_mm_test_all_onesのようなものでベクトル化されることを期待しました。どのようにしてループもベクトル化できますか? 2番目の質問、私は本当に大きなループの一部としてこれをしたいです。下のコメントを外すと、何もベクトル化されません。どのようにベクトル化することもできますか?

#define ARR_LENGTH 4096 
#define block_size 4 
typedef float afloat __attribute__ ((__aligned__(16))); 

char all_equal_2(afloat *a, afloat *b){ 
    unsigned int i, j; 
    char r = 1; 
    unsigned int temp[block_size] __attribute__((aligned(16))); 
    //for (i=0; i<ARR_LENGTH; i+=block_size){ 

     for (j = 0; j < block_size; ++j) { 
      temp[j] = (*a) == (*b); 
      a++; 
      b++; 
     } 

     for (j=0; j<block_size; j++){ 
      r &= temp[j]; 
     } 

     /*if (r == 0){ 
      break; 
     } 
    }*/ 
    return r; 
} 

、得られるアセンブリのキー部:

.cfi_startproc 
    movaps (%rdi), %xmm0 
    cmpeqps (%rsi), %xmm0 
    movdqa .LC0(%rip), %xmm1 
    pand %xmm0, %xmm1 
    movaps %xmm1, -24(%rsp) 
    movl -24(%rsp), %eax 
    andl $1, %eax 
    andb -20(%rsp), %al 
    andb -16(%rsp), %al 
    andb -12(%rsp), %al 
    ret 
    .cfi_endproc 

更新: このpostは私の最初の質問に似ています。その質問では、ベクトルは未処理のポインタだったので、segfaultsは可能ですが、ここではそれは問題ではありません。 AFAIKは比較操作を並べ替えるのが安全ですが、ここでは安全です。結論はおそらく同じです。

答えて

1

ループは静かに小さく、再帰的です。反復Nの結果は反復N + 1の入力として使用されます。 あなたがierationあたり2つの操作を許可するように第二のループを変更する場合:

 char r2 = r; 
    for (j=0; j<block_size/2; j+=2){ 
     r &= temp[j]; 
     r2 &=temp[j+1]; 
    } 
    r &= r2; 

を使用すると、出力は私が見有効コードの最適化と外側のループで、最後の点のために

.cfi_def_cfa_register %rbp 
vmovss (%rdi), %xmm0   ## xmm0 = mem[0],zero,zero,zero 
vmovss 4(%rdi), %xmm1   ## xmm1 = mem[0],zero,zero,zero 
vucomiss (%rsi), %xmm0 
sete %al 
vucomiss 4(%rsi), %xmm1 
sete %cl 
andb %al, %cl 
movzbl %cl, %eax 
popq %rbp 
retq 
.cfi_endproc 

を最適化されて表示されますいくつかの最適化。コンパイルオプションを変更しましたか?

+0

コンパイラフラグを "-03 -fopt-INFO-VEC-最適化" です。もちろん、gccはいくつかの最適化を行いますが、ベクトル化に特化しているのは、fopt-infoによって報告されているように、外部ループで最適化されたループは非コメント化されていません。また、浮動小数点のベクトル化をチェックする私の馬鹿のガイドは、* ps命令の束を探すことであり、一度外側ループが含まれていれば – user2133814

1

自動ベクトル化は実際に縮小操作が好きなので、これを減らすことがトリックでした。

#define ARR_LENGTH 4096 
typedef float afloat __attribute__ ((__aligned__(16))); 
int foo(afloat *a, afloat *b){ 
    unsigned int i, j; 
    unsigned int result; 
    unsigned int blocksize = 4; 
    for (i=0; i<ARR_LENGTH; i+=blocksize){ 
     result = 0; 
     for (j=0; j<blocksize; j++){ 
      result += (*a) == (*b); 
      a++; 
      b++; 
     } 
     if (result == blocksize){ 
      blocksize *= 2; 
     } else { 
      break; 
     } 
    } 
    blocksize = ARR_LENGTH - i; 
    for (i=0; i<blocksize; i++){ 
     result += (*a) == (*b); 
     a++; 
     b++; 
    } 
    return result == i; 
} 

素敵なループにコンパイル:私は使用しています、外側のループでとせずに

.L3: 
     movaps (%rdi,%rax), %xmm1 
     addl $1, %ecx 
     cmpeqps (%rsi,%rax), %xmm1 
     addq $16, %rax 
     cmpl %r8d, %ecx 
     psubd %xmm1, %xmm0 
     jb  .L3