哪一个更快更好?这种比较方法是真的吗?

时间:2017-10-17 08:52:54

标签: c performance optimization

我正在研究带有IAR编译器的STM8S微控制器。

我尝试比较d.M0.bit._5=d.M1.bit._7;的版本,并将循环和代码内存差异写为下面的命令。

typedef union 
{
 struct
 {
  unsigned char _0 :1;
  unsigned char _1 :1;
  unsigned char _2 :1;
  unsigned char _3 :1;
  unsigned char _4 :1;
  unsigned char _5 :1;
  unsigned char _6 :1;
  unsigned char _7 :1;
 } bit;
unsigned char data;
} m;

typedef struct 
{

  m M0,
    M1,
    M2,
    } dm_;

#pragma location = 0x050 
dm_ d;

// original version;

 d.M0.bit._5=d.M1.bit._7;   // 21 byte(difference from total code memory),
                            // 18 cycle (PC:Programme Counter)
//--------------------------------------------------------------------------   
// second version;

    d.M0.bit._5=0;          // 18 byte(difference from total code memory), 
   if(d.M1.bit._7)          // 15 cycle (PC:Programme Counter)
    d.M0.bit._5=1;

// third version;
    d.M0.data &=~(1<<5);    // 18 byte(difference from total code memory), 
   if(d.M1.data & 0x80)     // 15 cycle (PC:Programme Counter)
    d.M0.data |=(1<<5);

看来是这样,第二版和第三版比原版更平等,更有效但我不知道这是一个自信的比较吗?

在调试器模式下,我计算PC周期数并编译所有代码以检查每个代码存储器和新代码存储器的差异。

此外,它可能并不重要,但d.M0.bit._5=d.M1.bit._7;版本代码的汇编覆盖范围有更多汇编指令。

1 个答案:

答案 0 :(得分:1)

总的来说,最好避免使用ifs,因为除非你有条件移动指令,否则if == branch == slow。

从一个值到另一个值分配位的最短已知公式是:

r = a ^ ((a ^ b) & mask)

以下是公式的来源:https://graphics.stanford.edu/~seander/bithacks.html#MaskedMerge

因此,您案件的最终结果将是:

unsigned char a = d.M0.data;
unsigned char b = (d.M1.data >> 2); // put bit 7 into 5th position
unsigned char mask = 0x20; // will assign to a the 5th bit of b
d.M0.data = a ^ ((a ^ b) & mask);

在我的Intel i5上,它比其他选项快6-13%。我预计在较慢的CPU上差异会更明显。

但它有点棘手,所以如果速度增益值得代码可读性,那取决于你......

--------------------------------------------------------------
Benchmark                       Time           CPU Iterations
--------------------------------------------------------------
bits_assign                   212 ns        212 ns    3288700
bits_assign_if_bit            212 ns        210 ns    3327297
bits_assign_if_data           203 ns        203 ns    3457701
bits_assign_branchless        188 ns        188 ns    3713355