两个数组的逐位AND优化
Optimization of bitwise AND of two arrays
这似乎是一个简单的问题;我必须对两个数组进行逐位AND运算,如果任何两个位匹配,则返回true,基本上为:return ((dataArray & maskArray) != 0)
。
当然,这不是合法的C++。目前的解决方案类似于:
uint32_t dataArray[BIG_NUM] //Pretend it's initialized
uint32_t maskArray[BIG_NUM] //Pretend it's initialized
bool returnVal = false;
for(int i = 0; i < BIG_NUM; i++)
{
if((dataArray[i] & maskArray[i]) != 0)
{
returnVal = true;
break;
}
}
return returnVal;
它虽然是功能性的,但既不能并行化,也不能矢量化,因此很痛苦,在这个功能中消耗了10%的CPU周期。有没有想过如何清理它?
edit:意识到我不应该将底层成员sizeof()作为数组大小的一部分。
如果您通常返回false
,以下可能会更快:
bool res = 0;
for (int i = 0; i < BIG_NUM; i++)
{
res|= dataArray[i] & maskArray[i];
}
return res;
甚至
bool res = 0;
for (int i = 0; i < BIG_NUM; i++)
{
resArray[i] = dataArray[i] & maskArray[i];
}
for (int i = 0; i < BIG_NUM; i++)
{
res |= resArray[i];
}
return res;
取决于您的编译器
这里,这应该有助于矢量化,因为它只存在8的倍数,并且每八次计算只有一个分支预测(可能更快)。
for(int i = 0; i < BIG_NUM; i+=8)
{
uint32_t branch_once_per_8_calcs=0;
branch_once_per_8_calcs+=dataArray[i+0] & maskArray[i+0];
branch_once_per_8_calcs+=dataArray[i+1] & maskArray[i+1];
branch_once_per_8_calcs+=dataArray[i+2] & maskArray[i+2];
branch_once_per_8_calcs+=dataArray[i+3] & maskArray[i+3];
branch_once_per_8_calcs+=dataArray[i+4] & maskArray[i+4];
branch_once_per_8_calcs+=dataArray[i+5] & maskArray[i+5];
branch_once_per_8_calcs+=dataArray[i+6] & maskArray[i+6];
branch_once_per_8_calcs+=dataArray[i+7] & maskArray[i+7];
if(branch_once_per_8_calcs!= 0)
{
returnVal = true;
break;
}
}
您还可以将步长增加到64或128,并使用嵌套循环在每个步骤结束时检查一次,这样可以更快。
或
for(int i = 0; i < BIG_NUM; i+=8)
{
uint32_t branch_once_per_8_calcs=0;
branch_once_per_8_calcs+=(dataArray[i+0] & maskArray[i+0]) | (dataArray[i+1] & maskArray[i+1]);
branch_once_per_8_calcs+=(dataArray[i+2] & maskArray[i+2]) | (dataArray[i+3] & maskArray[i+3]);
branch_once_per_8_calcs+=(dataArray[i+4] & maskArray[i+4]) | (dataArray[i+5] & maskArray[i+5]);
branch_once_per_8_calcs+=(dataArray[i+6] & maskArray[i+6]) | (dataArray[i+7] & maskArray[i+7]);
if(branch_once_per_8_calcs!= 0)
{
returnVal = true;
break;
}
}
使用较少的添加和分配。别忘了检查溢出是否会导致假阴性。
相关文章:
- 空基优化子对象的地址
- 关闭||运算符优化
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- C++核心准则 C35 对于接口类"A base class destructor should be either public and virtual, or protected and nonv
- 为什么C++逐位AND运算符在不同大小的操作数中表现为这样
- 返回值优化:显式移动还是隐式
- 为什么 Clang 不允许"and"作为函数名称?
- 人脸跟踪arduino代码的优化
- 使用仅使用一次的变量调用的复制构造函数.这可能是通过调用move构造函数进行编译器优化的情况吗
- 位阵列上的快速AND运算
- 纯函数,为什么没有优化
- 是否可以在 C++03 中定义'move-and-swap idiom'等效项
- 为什么大多数 pair 实现默认不使用压缩(空基优化)?
- 如何以优化的方式同时迭代两个间距不相等的数组
- 小字符串优化(调试与发布模式)
- 浮点定向舍入和优化
- BoostPython and CMake
- OpenSSL BIO and SSL_read
- 两个数组的逐位AND优化
- 为什么 GCC 不能优化逻辑/按位 AND 对"x && (x & 4242)" "x & 4242"?