我有两个每个4个整数的向量,我想使用SIMD命令来比较它们(比如根据比较结果生成每个条目为0或1的结果向量).
然后,我想将结果向量与4个零的向量进行比较,并且只有在它们相等的情况下做一些事情.
你知道我可以用什么SIMD命令来做吗?
我需要检查所有向量元素是否为非零.到目前为止,我找到了以下解 有一个更好的方法吗?我在Linux/x86_64上使用gcc 4.8.2,指令直到SSE4.2.
typedef char ChrVect __attribute__((vector_size(16), aligned(16)));
inline bool testNonzero(ChrVect vect)
{
const ChrVect vzero = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
return (0 == (__int128_t)(vzero == vect));
}
Run Code Online (Sandbox Code Playgroud)
更新:上面的代码被编译为以下汇编代码(当编译为非内联函数时):
movdqa %xmm0, -24(%rsp)
pxor %xmm0, %xmm0
pcmpeqb -24(%rsp), %xmm0
movdqa %xmm0, -24(%rsp)
movq -24(%rsp), %rax
orq -16(%rsp), %rax
sete %al
ret
Run Code Online (Sandbox Code Playgroud) 我得到了一个小写字符数组(最多 1.5Gb)和一个字符 c。我想使用 AVX 指令查找字符 c 出现了多少次。
unsigned long long char_count_AVX2(char * vector, int size, char c){
unsigned long long sum =0;
int i, j;
const int con=3;
__m256i ans[con];
for(i=0; i<con; i++)
ans[i]=_mm256_setzero_si256();
__m256i Zer=_mm256_setzero_si256();
__m256i C=_mm256_set1_epi8(c);
__m256i Assos=_mm256_set1_epi8(0x01);
__m256i FF=_mm256_set1_epi8(0xFF);
__m256i shield=_mm256_set1_epi8(0xFF);
__m256i temp;
int couter=0;
for(i=0; i<size; i+=32){
couter++;
shield=_mm256_xor_si256(_mm256_cmpeq_epi8(ans[0], Zer), FF);
temp=_mm256_cmpeq_epi8(C, *((__m256i*)(vector+i)));
temp=_mm256_xor_si256(temp, FF);
temp=_mm256_add_epi8(temp, Assos);
ans[0]=_mm256_add_epi8(temp, ans[0]);
for(j=1; j<con; j++){
temp=_mm256_cmpeq_epi8(ans[j-1], Zer);
shield=_mm256_and_si256(shield, temp);
temp=_mm256_xor_si256(shield, FF);
temp=_mm256_add_epi8(temp, Assos);
ans[j]=_mm256_add_epi8(temp, ans[j]);
}
}
for(j=con-1; j>=0; …Run Code Online (Sandbox Code Playgroud) 如果SSE/AVX寄存器的值是所有字节都是0或1,有没有办法有效地获得所有非零元素的索引?
例如,如果xmm值为| r0 = 0 | r1 = 1 | r2 = 0 | r3 = 1 | r4 = 0 | r5 = 1 | r6 = 0 | ... | r14 = 0 | r15 = 1 | 结果应该是(1,3,5,...,15).结果应放在另一个_m128i变量或char [16]数组中.
如果它有帮助,我们可以假设寄存器的值是所有字节都是0或某个常量非零值(不是必需的1).
我非常想知道是否有关于那个或最好是C/C++内在的指令.在任何SSE或AVX指令集中.
编辑1:
@ zx485正确地观察到原始问题不够明确.我一直在寻找任何"连续"的解决方案.
0 1 0 1 0 1 0 1...上面的示例应该导致以下任一情况:
0将是终止字节,结果可能是002 004 006 008 010 012 014 016 000 000 000 000 000 000 000
001 003 …