【问题标题】:Remove if conditions from simple function从简单函数中删除 if 条件
【发布时间】:2016-01-12 15:52:55
【问题描述】:

我需要从以下两个函数中删除尽可能多的 if 条件:

inline int inc_with_1bit_saturation(int counter)
{
    if (counter == 1)
        return --counter;
    return ++counter;
}

void branch_prediction_1bit_saturation(int* input, int* output, int size)
{
    int counter = 0;

    for (int i = 0; i < size; ++i)
    {
        if (input[i] != counter)
        {
            counter = inc_with_1bit_saturation(counter);
            output[i] = 0;
        }
        else output[i] = 1;
    }
}

我该怎么做?if 分支是绝对必要的,不能删除,哪个可以用简单的按位运算或类似的东西代替?

更新 1

根据用户JSF 的精彩提示,代码现在如下所示:

void branch_prediction_1bit_saturation(int* input, int* output, int size)
{
    int counter = 0;

    for (int i = 0; i < size; ++i)
    {
        if (input[i] != counter)
        {
            counter = 1 - counter;
            output[i] = 0;
        }
        else output[i] = 1;
    }
}

更新 2

感谢Cantfindname,代码变成了这样:

void branch_prediction_1bit_saturation(int* input, int* output, int size)
{
    int counter = 0;

    for (int i = 0; i < size; ++i)
    {
        output[i] = counter == input[i];
        counter = output[i] * counter + (1 - output[i])*(1 - counter);
    }
}

这完全解决了这个问题。

【问题讨论】:

  • 您的代码counter = inc_with_1bit_saturation(counter); 是一种非常低效的方法来执行counter=1-counter; 第一个答案中的%2 方法也不是很好。

标签: c++ optimization micro-optimization


【解决方案1】:

对于循环内的if语句:

output[i] = (int)(input[i]==counter);
counter = output[i]*counter + (1-output[i])*(1-counter) //used JSF's trick

True 转换为 1,false 转换为 0,根据这个:bool to int conversion

【讨论】:

  • 位运算符可能更快:counter = (output[i] &amp; counter) | ((1-output[i]) &amp; (1-counter));
  • !(counter ^ output[i]) 也许 1-(counter ^ output[i]) 如果优化器不那么聪明,效果会更好。 counter^=(1-output[i]) 如果优化器真的很差。
【解决方案2】:

函数inc_with_1bit_saturation 等价于模2。所以你可以替换

counter = inc_with_1bit_saturation(counter);

counter = (counter+1) % 2;

【讨论】:

  • @Samidamaru:初始值为零。因此,它只能递增。然后它会得到 1 并且下一次调用会减少,所以再次为零。
  • 确实,意识到并删除了我的评论。 (虽然是其他函数的行为导致了这种行为,但函数本身并不执行模 2 ^^)。
  • counter = 1 - counter(@JSF建议)代替它比模运算好得多。
【解决方案3】:
void branch_prediction_1bit_saturation(int* input, int* output, int size) {

    int counter = 0;

    for (int i = 0; i < size; ++i)
    {
        output[i] = (int)!((!!input[i]) ^ counter);
        counter = (int)((!!input[i]) & counter) | ((!!input[i]) & !counter);
    }
}

A是逻辑输入[i];

B为逻辑计数器;

input[i] != counter 的真值表是:

甲乙

0 0 | 0 --> (0 & 0) | (0 & !0) = 0 | 0 = 0

0 1 | 0 --> (0 & 1) | (0 & !1) = 0 | 0 = 0

1 0 | 1 --> (1 & 0) | (1 & !0) = 0 | 1 = 1

1 1 | 1 --> (1 & 1) | (1 & !1) = 1 | 0 = 1

输出真值表[i]

甲乙

0 0 | 1 --> !(0 ^ 0) = !(0) = 1

0 1 | 0 --> !(0 ^ 1) = !(1) = 0

1 0 | 0 --> !(1 ^ 0) = !(1) = 0

1 1 | 1 --> !(1 ^ 1) = !(0) = 1

:)

【讨论】:

  • 您假设 input[i] 是 0 或 1。问题并未暗示这一点。
  • mmm..yes.. 将 (input[i]) 更改为 (!!input[i]),然后转换为 int。更新。
猜你喜欢
  • 2021-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-23
  • 2018-11-09
相关资源
最近更新 更多