我有一个int数组[10000],我想从某个位置迭代以找到下一个非零索引。目前我使用基本的while循环:
while(array[i] == 0){
pos++;
}
等
我知道使用内在函数我可以一次测试4个整数为零,但有没有办法返回指示“第一个”非零的向量索引的东西?
答案 0 :(得分:3)
执行此操作相当简单,但吞吐量提升可能不会很大,因为您可能会受到内存带宽的限制(除非您的阵列已经缓存):
int index = -1;
for (i = 0; i < n; i += 4)
{
__m128i v = _mm_load_si128(&A[i]);
__m128i vcmp = _mm_cmpeq_epi32(v, _mm_setzero_si128());
int mask = _mm_movemask_epi8(vcmp);
if (mask != 0xffff)
{
break;
}
}
if (i < n)
{
for (j = i; j < i + 4; ++j)
{
if (A[j] != 0)
{
index = j;
break;
}
}
}
这假设数组A
是16字节对齐的,其大小n
是4的倍数,并且整数是32位。
循环展开2倍可能会有所帮助,特别是如果您的输入数据很大和/或稀疏,例如。
int index = -1;
for (i = 0; i < n; i += 8)
{
__m128i v0 = _mm_load_si128(&A[i]);
__m128i v1 = _mm_load_si128(&A[i + 4]);
__m128i vcmp0 = _mm_cmpeq_epi32(v0, _mm_setzero_si128());
__m128i vcmp1 = _mm_cmpeq_epi32(v1, _mm_setzero_si128());
int mask0 = _mm_movemask_epi8(vcmp0);
int mask1 = _mm_movemask_epi8(vcmp1);
if ((mask0 | mask1) != 0xffff)
{
break;
}
}
if (i < n)
{
for (j = i; j < i + 8; ++j)
{
if (A[j] != 0)
{
index = j;
break;
}
}
}
如果您有AVX2(Haswell及更高版本),那么您可以一次处理8个整数而不是4个整数。