![]() |
1
58
您看到的是未优化的代码,因此研究它的性能并不是很有意义。如果你看
优化
为您的示例编写代码时,您会发现它根本无法进行比较!优化器注意到开关变量
优化器还可以看到变量
因此,优化后的代码对于您的任何一个版本都是相同的
简言之,对于问题中的代码,将
会不会
请务必注意Glenn和Lundin的评论:
顺序
的
编译器使用各种策略
|
![]() |
2
18
Compiler optimization
属于
(因此没有任何
如果您需要了解编译器如何优化
不 通常,如果您正在使用一些优化编译器并要求它进行优化。另请参见 this .
如果这对你来说如此重要(但不应该如此,把微优化留给你的编译器!),您需要进行基准测试、评测,或许还需要研究生成的汇编代码。顺便提一下
cache misses
和
register allocation
可能比订单更重要
如果你那么在乎性能,一定要
benchmark
和
profile
,并选择一个好的编译器,将其与相关优化选项一起使用。也许实验几种不同的
optimization
设置(可能还有几个编译器)。您可能需要添加
顺便说一句,许多编译器都很庞大 free software 项目(尤其是 通用条款 和 Clang ). 如果您非常关心性能,可以修补编译器,通过添加一些额外的优化过程(通过 forking 源代码,通过添加一些 plugin to GCC 或者一些 GCC MELT 扩展)。这需要数月或数年的工作(尤其是理解编译器的内部表示和组织)。 (别忘了考虑开发成本;在大多数情况下,开发成本要高得多) |
![]() |
3
6
性能主要取决于给定数据集的分支未命中数,而不是案例总数。而这又在很大程度上取决于实际数据以及编译器如何选择实现切换(调度表、链式条件、条件树——不确定是否可以从C中控制)。 |
![]() |
4
6
试图优化switch语句的一个困难是,编译器通常比程序员更清楚在给定某些输入时不同方法的性能如何变化,但程序员可能比编译器更清楚程序将接收到的输入分布。假设如下:
“智能”编译器可能会认识到将代码更改为:
可以消除所有情况下的比较
|
![]() |
5
5
switch语句通常通过以下方式编译: jump tables 不是通过简单的比较。 因此,如果您排列case语句,则不会损失性能。 然而,有时将更多案例保持连续顺序,并且在某些条目中不使用中断/返回是有用的,以便执行流转到下一个案例,并避免重复代码。
当数字之间的差异出现时
|
![]() |
6
4
你的问题很简单-你的代码不一样,所以它不会生成相同的程序集!优化的代码不仅取决于单个语句,还取决于它周围的一切。在这种情况下,很容易解释优化。 在第一个示例中,案例1的结果是a=1,案例2的结果是a=2。编译器可以对此进行优化,为这两种情况设置a=sc,这是一条语句。
如果你简单地拿第一个例子来交换案例的顺序 那么你应该得到相同的汇编程序。
这也应该给出完全相同的汇编程序。 顺便提一下,测试代码假设sc实际上已被读取。大多数现代优化编译器都能够发现sc在赋值和switch语句之间没有变化,并用常量值1代替读取sc。进一步优化将删除switch语句的冗余分支,然后甚至可以优化分配,因为a实际上没有改变。从变量a的角度来看,编译器还可能发现a没有在别处读取,因此将该变量从代码中完全删除。
如果您真的想读取sc并设置a,则需要同时声明它们
|
![]() |
7
4
在比较汇编代码之前,您可能应该启用编译器的优化,但是问题是,您的变量在编译时是已知的,因此编译器可以删除函数中的所有内容,因为它没有任何副作用。
This example
这表明,即使在示例中更改switch语句中事例的顺序,如果启用了优化,GCC和大多数其他编译器也会对其重新排序。
我使用了extern函数来确保只有在运行时才知道这些值,但我也可以使用
此外,当您添加更多案例时,编译器可能会用一个包含函数地址的表来替换条件跳转,并且它仍然会被GCC重新排序,如图所示 here . |
![]() |
S. Jacson · 任意两台发电机的速度差(内置功能) 2 年前 |
![]() |
Sadeq Dousti · 相当于“嵌套删除”的执行性能SQL查询 2 年前 |
![]() |
Prince · 复制大型文件需要更多时间 2 年前 |
![]() |
Sagar · 为什么在循环之外声明变量会更快? 2 年前 |
![]() |
seco · 如何在不挂起页面的情况下加载JS 2 年前 |