查看IF条件代码以节省CPU周期

时间:2017-08-29 15:28:03

标签: c if-statement

我正在审查我的程序中 if 条件的用法,在那里,我有以下几行:

if(count > 4) count = 4;

将上述 if 条件语句编写为以下非分支语句是不是一个好主意?

count = 4*(count> 4) + count*(count<= 4);

我还有以下片段:

for (j=0, i=0; j<NCARD_PER_SUIT && i<CARDS_PER_PLAYER+CARDS_ON_BOARD; ++j) {
    if (card_cfg.hearts & cfg_mask[j]) {
        player_hand[i].card.face = j;
        player_hand[i++].card.suit = HEART;
    }
    if (card_cfg.spades & cfg_mask[j]) {
        player_hand[i].card.face = j;
        player_hand[i++].card.suit = SPADE;
    }
    if (card_cfg.clubs & cfg_mask[j]) {
        player_hand[i].card.face = j;
        player_hand[i++].card.suit = CLUB;
    }
    if (card_cfg.diamonds & cfg_mask[j]) {
        player_hand[i].card.face = j;
        player_hand[i++].card.suit = DIAMOND;
    }
}

并想知道是否有良好的(非分支)方式来编写上述任何建议?

编辑:基于下面的一些反馈,我比较了装配说明(使用MSVS2015 for Windows 10)并获得了以下内容:

; 718  :     count = 4*(count> 4) + count*(count<= 4);

xor ebx, ebx
cmp edx, 4
setle   bl
xor ecx, ecx
imul    ebx, edx
cmp edx, 4
mov edx, 4
cmovg   ecx, edx
add ebx, ecx

如果恢复到if语句,我得到以下内容,其中没有跳转指令和指令总数2/3与上述相比:

; 718  :     if( count >4) count = 4;

mov eax, DWORD PTR _i$6$[ebp]
cmp edx, edi
mov ebx, DWORD PTR _player$GSCopy$1$[ebp]
cmovg   edx, edi
mov edi, DWORD PTR _count$1$[ebp]
mov DWORD PTR _count$4$[ebp], edx

编辑#2:根据以下评论中的提示,我继续创建

union 
typedef union {
    struct cfg {
        unsigned short hearts;  
        unsigned short spades;
        unsigned short clubs;
        unsigned short diamonds;
    } suit;
    unsigned long long allsuits;
} card_cfg_t;

在这个联盟的帮助下,我能够重写第二段OP,如下所示,如果我为64位机器构建并花费更多时间,这似乎可以节省很多(在我的情况下为20%)额外的40%)如果我为32位机器构建它:

for (j=0, i=0; j<NCARD_PER_SUIT && i<CARDS_PER_PLAYER+CARDS_ON_BOARD; ++j) {
    for (int k=0; k<4; ++k) {
        present = (int)((card_cfg.allsuits & (cfg_mask[j] << 16*k)) != 0);
        player_hand[i].card.face = j*present;
        player_hand[i].card.suit = k;
        i = i + present;
    }
}

2 个答案:

答案 0 :(得分:1)

那些微观优化并没有太多意义,但你想要比较(你会看到你和我之间的区别 - 开启优化 - 编译器真的很好):

int count;

 void foo()
 {
       count = 4*(count> 4) + count*(count <= 4);
 }

 void foo1()
 {
       count = count > 4 ? 4 : count;
 }

  void foo4()
 {
       if(count> 4) count = 4;
 }

foo:
  mov edx, DWORD PTR count[rip]
  xor ecx, ecx
  cmp edx, 4
  setle al
  setg cl
  movzx eax, al
  imul eax, edx
  lea eax, [rax+rcx*4]
  mov DWORD PTR count[rip], eax
  ret
foo1:
  cmp DWORD PTR count[rip], 4
  mov eax, 4
  cmovle eax, DWORD PTR count[rip]
  mov DWORD PTR count[rip], eax
  ret
foo4:
  cmp DWORD PTR count[rip], 4
  jle .L6
  mov DWORD PTR count[rip], 4
.L6:
  rep ret

答案 1 :(得分:1)

第二个循环的答案必须是:

     pushcards(player, popcards(dealer));