【问题标题】:Which one is faster and better? Is this compare method true?哪个更快更好?这种比较方法是真的吗?
【发布时间】:2017-10-17 08:52:54
【问题描述】:

我正在开发带有 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; 版本代码的汇编覆盖率具有更多汇编指令。

【问题讨论】:

  • 也对非位域解决方案进行基准测试。位字段是高度不可移植的——每个编译器几乎可以完全随意地实现它们——在底层数据中的顺序和位本身的顺序没有指定。通过使用它们,您很可能会将自己锁定在特定的编译器甚至平台中,具体取决于您的代码需要做什么。你可能不想被这样锁定。
  • “保密”是什么意思? “机密”(即“秘密”)似乎不适合这里。您是指“正确”、“可靠”之类的意思吗?
  • 启用了哪些优化?
  • @Fabio Turati 我的意思是“这种比较方法可靠吗。”
  • @Lundin 在 IAR Workbech 编译器优化设置中,已激活高级优化。 (启用的转换:通用子表达式消除、循环展开、函数内联、代码运动、基于类型的别名分析和交叉调用)

标签: c performance optimization


【解决方案1】:

总体而言,最好避免使用 if,因为除非您有条件移动指令,否则 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

【讨论】:

    猜你喜欢
    • 2017-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-10
    相关资源
    最近更新 更多