C++位掩码/条件分支优化
C++ bitmask / conditional branch optimization
我正在尝试减少下面显示的if语句(第二块代码)的执行时间。 它涉及一个位掩码,其中掩码数组包含 8 个用作掩码的整数,并设置如下:
static unsigned int masks[8];
void setupMasks() {
int mask = 3; // 0000 0000 0000 0000 0000 0000 0000 0011
for(unsigned int i=0; i < 8; i++) {
masks[i] = (mask << (i * 4));
}
}
下面 testarr 中的每个整数实际上包含 8 个结果。 每个结果是 32 位 int 的 4 位,我只想知道 4 位中的下两位是否有任何位是 1。 下面的代码在另一个更新结果的 for 循环中执行。 失败计数是一个本地定义的 int 数组。 我想避免屏蔽,但 testarr 中的数据来自我无法更改的 API。 无论如何,我认为 if 语句比掩蔽花费更多的时间,但我可能是错的。 有没有人看到优化的方法?
for(unsigned int i = 0; i < 8 && dumped < numtodump; i++, dumped++) { //8 results per 32-bit value
unsigned int fails = 0;
for(unsigned int j = 0; j < 32; j++) {
if((testarr[j * numintsperpin + resultnum] & masks[i]) && failcount[j]++ <= 10000) { //have a fail
failingpins[fails++] = &pins[j];
}
}
}
对不起,如果我之前的帖子不清楚。 以下是完整功能。我试图尽可能简化问题陈述。 抱歉,如果我遗漏了有用的细节。
void process(vector<int> &testarr, vector<unsigned int> &failcount, vector<pin> &pins, vector<unsigned int> &muxaddr, unsigned int base, StopWatch &acc1) {
unsigned int labeloffset = 400;
unsigned int startindex = 50;
unsigned int numtodump = 1000;
unsigned int numintsperpin = testarr.size() / pins.size();
pin** failingpins = new pin*[32];
acc1.start();
int count = 0;
unsigned int dumped = 0;
unsigned int resultnum = 0;
while(dumped < numtodump) {
for(unsigned int i = 0; i < 8 && dumped < numtodump; i++, dumped++) { //8 results per 32-bit value
unsigned int currentindex = labeloffset + dumped + startindex;
unsigned int fails = 0;
for(unsigned int j = 0; j < pins.size(); j++) {
if((testarr[j * numintsperpin + resultnum] & masks[i]) && failcount[j]++ <= 10000) { //have a fail
failingpins[fails++] = &pins[j];
}
}
unsigned int saddr = muxaddr[currentindex];
if(fails > 0) {
logFails(fails, muxaddr[currentindex] - base, failingpins);
}
}
resultnum++;
}
acc1.accumulate();
}
看看我是否有这个权利:
testarr 中的每个条目都是一个 32 位值,包含 8 x 4 位字段
您想知道是否有任何字段设置了较低的 2 位中的任何一个,即您希望用以下方法屏蔽每个 32 位值:
0011 0011 0011 0011 0011 0011 0011 0011
那为什么不呢:
for( int i=0; i<testarr_length; i++ )
if( testarr[i] & 0x33333333 )
// do something !
如果您需要知道设置了多少个字段,则
for( int i=0; i<testarr_length; i++ )
{
unsigned int dword= testarr[i];
for( int field=0; field<8; field++ )
{
if( dword & 0x3 )
// do something
dword= dword >> 4;
}
}
您可以尝试以下操作
inline int count(int x)
{
static int mask1 = 0x11111111;
static int mask2 = 0x22222222;
return __builtin_popcount(x & mask1 | x & mask2 << 1);
}
// ...
unsigned int fails = 0;
for(unsigned int j = 0; j < 32; j++) {
int c = count(testarr[j * numintsperpin + resultnum]);
if(c && (failcount[j]+=c) <= 10000) { //have a fail
failingcols[fails+=c] = &column[j];
}
}
其中我将掩码拆分为两个单独的掩码,并使用了函数__builtin_popcount
,该函数仅在一个 CPU 操作中计算给定整数的位数,从而完全避免了i
循环。
__builtin_popcount
应该由编译器提供,例如,上面的示例适用于带有选项 -msse4.2
的 Clang 和 GCC。据我所知,MS编译器分别提供了函数__popcnt
。
我不知道dumped
的作用是什么,但它没有显示在你的循环中,所以我只是忽略了它。
编辑
我现在看到了更新的问题,除了失败的数量之外,dumped
似乎在重新编码失败的实际位置方面发挥着重要作用。在这种情况下,我的解决方案不适用。这个新问题更难优化。
- 空基优化子对象的地址
- IPC使用多个管道和分支进程来运行Python程序
- 关闭||运算符优化
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- 如何删除peer if else分支中的冗长句子
- 如何确保在使用基于布尔值的两个方法之一调用方法时避免分支预测错误
- C++位掩码/条件分支优化
- 分支预测优化
- 通过将"goto"转换为分支机构进行优化
- 如何优化因 CPU 分支未命中而减慢的跳转指令
- 使用分支优化 CUDA 代码
- 针对已知的更常见的路径优化分支
- 优化:昂贵的分支vs廉价的比较
- 模板函数分支优化
- 分支预测及分支目标预测优化
- 为什么GCC没有尽可能地优化这组分支和条件?
- 为什么VS 2015编译器不能在浮点数的abs()实现中优化分支?
- 如何使每帧分支优化友好
- 帮助编译器优化分支代码序列
- 编译器有一定的优化启发式来支持分支预测吗?如果没有,为什么没有呢?