Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/144.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如果使用较小的数字,开关盒是否更快?_C++_Switch Statement - Fatal编程技术网

C++ 如果使用较小的数字,开关盒是否更快?

C++ 如果使用较小的数字,开关盒是否更快?,c++,switch-statement,C++,Switch Statement,我想知道如果我在switch case语句中通过一些偏移量(或类似的东西)更改“巨大”数字,是否可以优化某些内容。所以我做了一个测试: #include <iostream> #include <iomanip> #include <chrono> int main() { uint32_t f = 0x12345688; std::chrono::time_point<std::chrono::system_clock> st

我想知道如果我在
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() << "s\n";

    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() << "s\n";

    return 0;
}
#包括
#包括
#包括
int main(){
uint32_t f=0x12345688;
std::chrono::时间点开始、结束;
int i=-1;
开始=标准::时钟::系统时钟::现在();
开关(f)
{
案例0x1234500:i=0;中断;
案例0x1234522:i=2;中断;
案例0x1234555:i=5;中断;
案例0x1234588:i=8;中断;
默认:中断;
}
end=std::chrono::system_clock::now();
std::chrono::持续时间(秒)=结束-开始;

std::cout这种基准测试方法毫无意义,因为编译器可以在这两种情况之间静态地确定
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() << "s\n";

// 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;
start=std::chrono::system_clock::now();
开关(f)
{
案例0x1234500:i=0;中断;
案例0x1234522:i=2;中断;
案例0x1234555:i=5;中断;
案例0x1234588:i=8;中断;
默认:中断;
}
end=std::chrono::system_clock::now();
std::chrono::持续时间(秒)=结束-开始;

std::cout这种基准测试方法毫无意义,因为编译器可以在这两种情况之间静态地确定
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() << "s\n";

// 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;
start=std::chrono::system_clock::now();
开关(f)
{
案例0x1234500:i=0;中断;
案例0x1234522:i=2;中断;
案例0x1234555:i=5;中断;
案例0x1234588:i=8;中断;
默认:中断;
}
end=std::chrono::system_clock::now();
std::chrono::持续时间(秒)=结束-开始;

std::cout对于性能来说,最重要的一点是,数字是连续的。这是因为编译器可以使用该值来索引内存地址,该地址指定开关应该跳转到哪里来处理所讨论的情况。较大的间隔使得索引不可能,因为它会跳转很远,编译器将ld必须插入大量的空代码来填充未使用的空间

较小的数字可以使它稍微快一点-您可能只保存一条指令,因为编译器可以进行减法运算,然后仍然可以使用索引


以上所有内容都依赖于编译器。愚蠢的编译器可能根本不使用索引。

对于性能而言,最重要的一点是数字是连续的。这是因为编译器可以使用该值来索引内存地址,该地址指定开关应跳转到哪里来处理有问题的情况。大gaps使得索引变得不可能,因为它会跳得很远,编译器必须插入大量的空代码来填充未使用的空间

较小的数字可以使它稍微快一点-您可能只保存一条指令,因为编译器可以进行减法运算,然后仍然可以使用索引



所有这些都依赖于编译器。一个愚蠢的编译器可能根本不使用索引。

我想这不是一个可以通过一次迭代可靠测试的东西。@Rotem特别是考虑到使用刷新写入流是一个非常耗时的操作,这比任何可能的转换都要慢。您是否考虑过您的编译器iler可能已经完全优化了switch语句?如果你可以使用这些简单的技巧使语言的基本构建块更快,那么为什么编译器不应该总是在幕后进行呢?要从中获得任何有意义的东西,只需反汇编优化的代码,看看你得到了什么。我想这不是什么通过一次迭代,您可以可靠地进行测试。@Rotem特别是考虑到使用刷新写入流是一个非常耗时的操作,这比任何可能的切换都慢得多。您是否考虑到您的编译器可能已经完全优化了switch语句?如果您可以使用这些简单的技巧来创建基本的构建blo语言的速度更快,那么为什么编译器不应该总是在幕后进行呢?要从中获得任何有意义的东西,只需反汇编优化的代码,看看你得到了什么。问题是“如果数字更小,速度会更快吗?”所以,我不理解删除I的想法。我可以使用另一个int j=-1;并根据f改变它的值,所以…我将更新代码一次more@sop是的,我理解这个问题。但是,由于您使用固定常量作为输入,编译器将优化代码,您的测试将没有意义。如上所述。以及不,更改变量名不会影响这一点。问题是输入,变量
f
。因此,如果我更改f的值,会更好吗?@sop只需读取答案。您需要在运行时为
f
指定一个值。例如,从文件中读取该值。此外,将原始代码扔进一个运行10亿次的循环也不会有什么好处因为循环只是处理编译时常量。它会得到优化。问题是“如果数字更小,它会更快吗?”所以,我不理解删除I的想法。我可以使用另一个int j=-1;并根据f改变它的值,所以…我将更新代码一次more@sop是的,我理解这个问题。但是,由于您使用固定常量作为输入,编译器将优化代码,您的测试将没有意义。如上所述。以及不,更改变量名不会影响这一点。问题是输入,变量
f
。因此,如果我更改f的值,会更好吗?@sop只需读取答案。您需要在运行时为
f
指定一个值。例如,从文件中读取该值。此外,将原始代码扔进一个运行10亿次的循环也不会有什么好处实现任何东西,因为循环只是处理编译时常量