如何自动矢量化数组比较function

这是这篇文章的后续内容。 免责声明:我做过零分析,甚至没有应用程序,这纯粹是为了让我学习更多关于矢量化的知识。

我的代码如下。 我正在使用g3 4.9.4在配备i3 m370的机器上进行编译。 第一个循环按照我的预期进行矢量化。 然而,检查每个temp元素的第二个循环不是矢量化的AFAICT,带有所有“andb”指令。 我希望它可以像_mm_test_all_ones那样进行矢量化。 该循环如何进行矢量化? 第二个问题,我真的希望这是一个更大的循环的一部分。 如果我取消注释下面的内容,则没有任何内容可以进行矢量化。 我怎样才能得到那个矢量化?

#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 

更新:这篇文章与我的第一个问题类似。 在那个问题中,向量是一个原始指针,因此段错误是可能的,但这里不是一个问题。 因此,AFAIK重新排序比较操作在这里是安全的,但不是那里。 结论可能是相同的。

所以你的循环很小并且它是递归的:迭代的结果N在迭代N + 1中用作输入。 如果您更改第二个循环以允许每个操作2次操作:

  char r2 = r; for (j=0; j 

你会看到输出是优化的

 .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 

最后一点,在优化代码并启用外部循环后,我看到了一些优化。 你有没有改变编译选项?

自动向量化确实喜欢减少操作,因此诀窍是将其转化为减少。

 #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 

编译成一个很好的循环:

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