如果使用较小的数字,则开关案例更快
Is switch case faster if using smaller numbers?
我想知道,如果我在 switch-case
语句中通过某些偏移(或类似的东西)更改"巨大"数字是否可以优化某些内容。所以我做了一个测试:
#include <iostream>
#include <iomanip>
#include <chrono>
int main() {
uint32_t f = 0x12345688;
std::chrono::time_point<std::chrono::system_clock> start, end;
int i = -1;
start = std::chrono::system_clock::now();
switch (f)
{
case 0x1234500 : i = 0; break;
case 0x1234522 : i = 2; break;
case 0x1234555 : i = 5; break;
case 0x1234588 : i = 8; break;
default : break;
}
end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = end-start;
std::cout << "elapsed time: " << elapsed_seconds.count() << "sn";
int j = -1;
start = std::chrono::system_clock::now();
switch (f & 0xf)
{
case (0x1234500 & 0xf) : j = 0; break;
case (0x1234522 & 0xf) : j = 2; break;
case (0x1234555 & 0xf) : j = 5; break;
case (0x1234588 & 0xf) : j = 8; break;
default : break;
}
end = std::chrono::system_clock::now();
elapsed_seconds = end-start;
std::cout << "elapsed time: " << elapsed_seconds.count() << "sn";
return 0;
}
似乎总是第二个开关案例更快。
有理由使案例中的小数字更快地进行声明(案例之间的"差距"相同)?
此基准测试方法是胡说八道,因为编译器可以静态地确定两种情况之间的i
值。您的实际代码可能最终会出现这样的内容:
start = std::chrono::system_clock::now();
switch (f)
{
case 0x1234500 : i = 0; break;
case 0x1234522 : i = 2; break;
case 0x1234555 : i = 5; break;
case 0x1234588 : i = 8; break;
default : break;
}
end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = end-start;
std::cout << "elapsed time: " << elapsed_seconds.count() << "sn";
// i = -1; this line isn't needed, the value isn't used, lets optimize it away
start = std::chrono::system_clock::now();
// Oh great, we already know the value of i
// Because nothing in the previos code could have affected f
// i will get the same value as it did above, and we removed i = -1
// So lets optimize away this pointless code here
end = std::chrono::system_clock::now();
elapsed_seconds = end-start;
您可以尝试将i
声明为volatile
,但这可能会阻止编译器其他进行优化,因此它可能不会进行有效的基准测试。
测试之间的i = -1;
是没有意义的,因为编译器可以扣除该值未使用。因此,该代码也会被删除。
最好的方法可能是从文件或用户输入中读取常数0x12345688
,以便编译器无法对其进行任何假设。对于两个测试用例,您需要两次。
一般:这样的基准测试时,请始终拆卸代码,以验证您的测试不是胡说八道。
性能最重要的是,数字是连续。这是因为编译器可以使用该值来索引内存地址,该内存地址指定开关应在何处跳动以处理相关情况。大差距使索引变得不可能,因为它会跳得很远,并且编译器将不得不插入大量的空代码以填补未使用的空间。
少量数字可以使它少量更快 - 您只能保存一个指令,因为编译器可以减去,然后能够静止使用索引。
上述所有内容均取决于编译器。愚蠢的编译器可能根本不使用索引。
相关文章:
- C 和 C++ 中开关语句的案例标签的常量值,但显示不同的行为
- 正在读取开关案例中的.txt文件
- C++实用程序,用于将长开关语句转换为封装开关案例阶梯的简洁函数调用
- 执行默认值:在C 中的开关案例选择语句中
- 在开关案例节点中,将const int int指向int
- 使用开关语句案例中的随机数
- 案例和开关问题
- 如何在 c++ 中使用开关中的案例条件作为变量
- 如果使用较小的数字,则开关案例更快
- 我可以在c 中的语句中使用开关案例的情况吗?
- 没有默认标签的开关案例中的无效值
- 在开关案例内将字符串化
- 如何从案例 4 调用开关案例 5
- 状态机:使用转换矩阵而不是嵌套的开关案例C++
- 在 c++ 开关案例中引入循环
- C++、开关案例和编译器
- 新设置开关案例arduino
- 在开关案例语句中,它说"duplicate case value"出现错误。有人知道为什么吗?
- C++中的动态开关案例
- 抽象/重构此开关/案例的好方法是什么?