两个数组的按位AND优化

时间:2015-03-23 20:02:36

标签: c++ optimization c++03

似乎是一个简单的问题;我必须采用两个数组的按位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周期在此功能中被烧毁。有关如何清理它的想法吗?

编辑:意识到我不应该将底层成员sizeof()作为数组大小的一部分。

2 个答案:

答案 0 :(得分:2)

如果您通常返回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;

取决于您的编译器

答案 1 :(得分:0)

在这里,这应该有助于矢量化,因为它只退出8的倍数,并且每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;
    }
}

使用较少的添加和分配。别忘了检查可能导致漏报的溢出。