代码之家  ›  专栏  ›  技术社区  ›  torb

交换机案例优化方案

c
  •  0
  • torb  · 技术社区  · 7 年前

    问题是:

    void func( int num)
    
    set = 1,2,3,4,6,7,8,10,11,15
    
    {
         if (num is not from set )
      regular_action();
         else
          unusual_stuff();
    }
    

    这个集合总是有上面提到的值,或者类似于许多元素的值。

    例如。

    set = 0,2,3,6,7,8,11,15,27

    在我的程序运行期间,传递的no大多数时候不是来自这个集合,但是当它来自这个集合时,我需要采取一些操作。

    我试图用下面的函数来模拟上面的行为,以确定switch语句的编写方式。下面的函数除了switch case-jump tables-comparison之外什么也不做。

    compare_1 是更快还是 compare_2 更快。在我的双核机器上, 比较2 总是看起来更快,但我不明白为什么会这样?编译器是否如此聪明以至于在这种情况下也能进行优化?

    5 回复  |  直到 15 年前
        1
  •  2
  •   Jens Gustedt    15 年前

    没有办法 感觉 一个功能比另一个快。进行测量(不使用 printf )并比较生成的汇编程序(使用选项 -S 给编译器)。

        2
  •  1
  •   Thomas Matthews    15 年前

    下面是一些优化 switch 声明:

    移除 转换 陈述

    转换 不需要声明。例如,在基类中实现虚拟基类方法。或者使用数组。

    过滤掉常见的选择。如果一个范围内有许多选择,请将这些选择减少到该范围内的第一项(尽管编译器可能会自动为您这样做)

    保持选项连续

    对于编译器来说,这很容易实现为一个单索引跳转表。

    很多选择,不是连续的

    一种方法是实现关联的数组(键、函数指针)。守则 可以 搜索表或查找较大的表,它们可以实现为链接列表。其他选择是可能的。

    通常由编译器作为 if-elseif 梯子。

    剖析

    真正的证明是在设置编译器优化开关和分析。

    程序集列表

    您可能需要编写一些switch语句,并查看编译器如何生成程序集代码。查看哪个版本为您的情况生成最佳的程序集代码。

        3
  •  1
  •   R.. GitHub STOP HELPING ICE    15 年前

    如果集合中确实包含0到63之间的数字,请使用:

    #define SET 0x.......ULL
    if (num < 64U && (1ULL<<num & SET)) foo();
    else bar();
    
        4
  •  0
  •   Darren    11 年前

    总是 默认大小写必须始终显示为开关中的最后一个大小写。见 http://www.tutorialspoint.com/cplusplus/cpp_switch_statement.htm 例如,如果switch语句声明“switch语句可以有一个可选的默认大小写,它必须出现在switch的末尾。默认情况可用于在没有任何情况为真时执行任务。默认情况下不需要中断。”

        5
  •  -1
  •   Tom    15 年前

    下面是上面提到的功能

    #define MAX 100000000
    void compare_1(void)
    {
       unsigned long i;
       unsigned long j;
       printf("%s\n", __FUNCTION__);
       for(i=0;i<MAX;i++)
       {
          j = rand()%100;
          switch(j)
          {
        case 1:
        case 2:
        case 3:
        case 4:
        case 6:
        case 7:
        case 8:
        case 10:
        case 11:
        case 15:
           break   ;
        default:
           break   ;
          }
       }
    }
    
    
    void unreg(void)
    {
       int i;
       int j;
       printf("%s\n", __FUNCTION__);
       for(i=0;i<MAX;i++)
       {
          j = rand()%100;
          switch(j)
          {
        default:
           break   ;
        case 1:
        case 2:
        case 3:
        case 4:
        case 6:
        case 7:
        case 8:
        case 10:
        case 11:
        case 15:
           break   ;
          }
       }
    }