使用内部函数在数组中查找下一个非零
Using intrinsics to find next non-zero in an array
我有一个int数组[10000],我想从某个位置迭代以找到下一个非零索引。目前我使用一个基本的while循环:
while(array[i] == 0){
pos++;
}
etc
我知道使用内部函数,我可以一次测试4个整数的零,但有没有办法返回指示"第一个"非零的向量索引?
这很简单,但吞吐量的提高可能不会很大,因为您可能会受到内存带宽的限制(除非您的阵列已经缓存):
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的倍数,int是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个int,而不是4个。
相关文章:
- 重新定位图像时如何前进到下一个内存块
- 为什么C++对链表中的下一个节点使用指针,而像 C# 或 Java 这样的语言只使用类 Node 的名称?
- 用于在 C++ 中使用 while 循环查找下一个素数的简单函数
- CIN 仅在输入非数字值时跳过下一个 CIN
- 查找最小的下一个更大的元素
- 转到基于范围的 for 循环中的下一个迭代器
- 如何检查流中文件的下一个单词是否为 alpha?
- 使用一个内存集数组和单个堆栈在 O(n) 中查找数组的下一个更大元素
- 查找下一个具有真值C++的数组索引
- 检查IP是否在其他IP网络范围内,并查找下一个可用IP
- 使用堆栈查找每个元素的下一个更大的元素
- 使用 Windows 寄存器查找下一个"Daylight Saving Time"
- 查找第一个文件/查找下一个文件不返回文件夹中的所有文件
- 查找下一个文件失败,出现空格字符
- 在内存池中查找下一个可用区块
- 如何使用 std::regex 查找字符串中的下一个匹配项
- C++ 如何查找下一个字符 std::cout 是否位于控制台行的开头
- 查找下一个素数回文
- 使用内部函数在数组中查找下一个非零
- 查找下一个对齐的内存地址