Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.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_Optimization - Fatal编程技术网

C 优化案例陈述

C 优化案例陈述,c,optimization,C,Optimization,我们有一种将命令数据写入设备的方法。该方法首先将数据转换为设备接受的格式,然后将数据写入串行端口。数据转换使用下面给出的case语句完成。对于10个命令,我们需要转换数据。对于其他命令,我们不必转换数据(大约10个命令) 客户投诉代码未优化。一些不需要数据转换的命令经常使用 direct if else语句会优化代码吗? 在这种情况下,是否有其他选项来优化代码 switch (cmd_no) { case CMD_WR_ACC: converted_command_data = (INT

我们有一种将命令数据写入设备的方法。该方法首先将数据转换为设备接受的格式,然后将数据写入串行端口。数据转换使用下面给出的case语句完成。对于10个命令,我们需要转换数据。对于其他命令,我们不必转换数据(大约10个命令)

客户投诉代码未优化。一些不需要数据转换的命令经常使用

direct if else语句会优化代码吗?
在这种情况下,是否有其他选项来优化代码

switch (cmd_no)
{
case CMD_WR_ACC:
    converted_command_data = (INT32)((((DOUBLE)cmd_data * CMD_WR_ACC_PARA1) / CMD_WR_ACC_PARA2) + 0.5);
    break;
case CMD_WR_BIAS:
    converted_command_data = (INT32)((((DOUBLE)cmd_data * CMD_WR_BIAS_PARA1) / CMD_WR_BIAS_PARA2) + 0.5);
    break;
case CMD_WR_SUP:
    converted_command_data = (INT32)((((DOUBLE)cmd_data * CMD_WR_SUP_PARA1) / CMD_WR_SUP_PARA2) + 0.5);
    break;
case CMD_WR_FIL:
    converted_command_data = (INT32)((((DOUBLE)cmd_data * CMD_WR_FIL_PARA1) / CMD_WR_FIL_PARA2) + 0.5);
    break;
    .
    .
default:
    converted_command_data = cmd_data;
    break;
}
如果客户所说的“未优化”意味着重复,那么看起来您可以在表中列出大量的逻辑

假设您的命令类型是按顺序编号的,即

#define CMD_WR_ACC 0
#define CMD_WR_BIAS 1
#define CMD_WR_SUP 2
...
您可以这样定义表:

struct params {
    int convert;       // whether or not to convert
    double param1;
    double param2;
} params_table[] = {
    { 1, CMD_WR_ACC_PARA1, CMD_WR_ACC_PARA2 },
    { 1, CMD_WR_BIAS_PARA1, CMD_WR_BIAS_PARA2 },
    { 1, CMD_WR_SUP_PARA1, CMD_WR_SUP_PARA2 },
    ...
    { 0, 0, 0}
    ...
};
if (params_table[cmd_no].convert) {
    converted_command_data = (INT32)((((DOUBLE)cmd_data * 
         params_table[cmd_no].param1) / params_table[cmd_no].param2) + 0.5);
} else {
    converted_command_data = cmd_data;
}
然后,您的代码如下所示:

struct params {
    int convert;       // whether or not to convert
    double param1;
    double param2;
} params_table[] = {
    { 1, CMD_WR_ACC_PARA1, CMD_WR_ACC_PARA2 },
    { 1, CMD_WR_BIAS_PARA1, CMD_WR_BIAS_PARA2 },
    { 1, CMD_WR_SUP_PARA1, CMD_WR_SUP_PARA2 },
    ...
    { 0, 0, 0}
    ...
};
if (params_table[cmd_no].convert) {
    converted_command_data = (INT32)((((DOUBLE)cmd_data * 
         params_table[cmd_no].param1) / params_table[cmd_no].param2) + 0.5);
} else {
    converted_command_data = cmd_data;
}
如果命令的起始索引不是0,则需要从
cmd\u no
中减去最低的命令编号,才能将索引放入表中。

如果“未优化”意味着重复,则您可以将大量此逻辑放入表中

假设您的命令类型是按顺序编号的,即

#define CMD_WR_ACC 0
#define CMD_WR_BIAS 1
#define CMD_WR_SUP 2
...
您可以这样定义表:

struct params {
    int convert;       // whether or not to convert
    double param1;
    double param2;
} params_table[] = {
    { 1, CMD_WR_ACC_PARA1, CMD_WR_ACC_PARA2 },
    { 1, CMD_WR_BIAS_PARA1, CMD_WR_BIAS_PARA2 },
    { 1, CMD_WR_SUP_PARA1, CMD_WR_SUP_PARA2 },
    ...
    { 0, 0, 0}
    ...
};
if (params_table[cmd_no].convert) {
    converted_command_data = (INT32)((((DOUBLE)cmd_data * 
         params_table[cmd_no].param1) / params_table[cmd_no].param2) + 0.5);
} else {
    converted_command_data = cmd_data;
}
然后,您的代码如下所示:

struct params {
    int convert;       // whether or not to convert
    double param1;
    double param2;
} params_table[] = {
    { 1, CMD_WR_ACC_PARA1, CMD_WR_ACC_PARA2 },
    { 1, CMD_WR_BIAS_PARA1, CMD_WR_BIAS_PARA2 },
    { 1, CMD_WR_SUP_PARA1, CMD_WR_SUP_PARA2 },
    ...
    { 0, 0, 0}
    ...
};
if (params_table[cmd_no].convert) {
    converted_command_data = (INT32)((((DOUBLE)cmd_data * 
         params_table[cmd_no].param1) / params_table[cmd_no].param2) + 0.5);
} else {
    converted_command_data = cmd_data;
}

如果命令的起始索引不是0,则需要从
cmd\u no
中减去最低的命令编号,才能将索引放入表中。

将代码从开关重写为If/then/else不会有太大的改进。首先要尝试的是将优化选项设置为最高值进行编译。我想,让编译器为您优化它。这就是低垂的果实通常所在的地方

这有什么帮助? 默认情况下,GCC平衡了代码速度优化与代码大小和调试容易性。默认情况下,gcc生成易于调试的代码,因为代码流与源代码更接近,并且存储了变量(速度较慢),但这使得使用gdb和断点进行调试更容易,因为变量在堆栈上很容易看到

当我们打开优化时,会进行更多的优化,包括只在处理器寄存器中存储一些局部变量(速度很快),以及通过重新排序代码来优化cpu执行管道中的代码流。缺点是当单步执行机器代码时更难遵循。编译也需要稍长的时间但这是值得的

要在优化标志设置为最高值的情况下进行编译,请尝试-O3,它会对代码大小和执行时间设置更多优化:

-O3
关于优化标志,这里有一个很好的讨论:

在使用优化标志集编译之后,请查看使用昂贵浮点运算的数学。你需要它们吗?双乘法和除法很昂贵,只是为了将它们转换成INT32?你确定需要这样做吗。你能把数学转换成只使用整数运算吗


您可以共享列出的常量的值吗?您可能能够将部分或全部数学转换为查找表。

将代码从一个开关重写为if/then/else不会有太大的改进。首先要尝试的是将优化选项设置为最高值进行编译。我想,让编译器为您优化它。这就是低垂的果实通常所在的地方

这有什么帮助? 默认情况下,GCC平衡了代码速度优化与代码大小和调试容易性。默认情况下,gcc生成易于调试的代码,因为代码流与源代码更接近,并且存储了变量(速度较慢),但这使得使用gdb和断点进行调试更容易,因为变量在堆栈上很容易看到

当我们打开优化时,会进行更多的优化,包括只在处理器寄存器中存储一些局部变量(速度很快),以及通过重新排序代码来优化cpu执行管道中的代码流。缺点是当单步执行机器代码时更难遵循。编译也需要稍长的时间但这是值得的

要在优化标志设置为最高值的情况下进行编译,请尝试-O3,它会对代码大小和执行时间设置更多优化:

-O3
关于优化标志,这里有一个很好的讨论:

在使用优化标志集编译之后,请查看使用昂贵浮点运算的数学。你需要它们吗?双乘法和除法很昂贵,只是为了将它们转换成INT32?你确定需要这样做吗。你能把数学转换成只使用整数运算吗

您可以共享列出的常量的值吗?您可以将部分或全部数学转换为查找表

directif-else语句会优化代码吗

否,
if-else if
的列表与在机器代码级别上使用
开关
完全相同,因为
if-else if
的性质相同

if(integer == 1) 
{ ... }  
else if (integer == 2) 
{ ... }
其中1和2是任何类型的编译时整数常量。在这种情况下,它将产生100%的等效机器代码

switch(integer)
{
  case 1: ... break;
  case 2: ... break;
}

在这种情况下,是否有其他选项来优化代码

switch (cmd_no)
{
case CMD_WR_ACC:
    converted_command_data = (INT32)((((DOUBLE)cmd_data * CMD_WR_ACC_PARA1) / CMD_WR_ACC_PARA2) + 0.5);
    break;
case CMD_WR_BIAS:
    converted_command_data = (INT32)((((DOUBLE)cmd_data * CMD_WR_BIAS_PARA1) / CMD_WR_BIAS_PARA2) + 0.5);
    break;
case CMD_WR_SUP:
    converted_command_data = (INT32)((((DOUBLE)cmd_data * CMD_WR_SUP_PARA1) / CMD_WR_SUP_PARA2) + 0.5);
    break;
case CMD_WR_FIL:
    converted_command_data = (INT32)((((DOUBLE)cmd_data * CMD_WR_FIL_PARA1) / CMD_WR_FIL_PARA2) + 0.5);
    break;
    .
    .
default:
    converted_command_data = cmd_data;
    break;
}
有几件事:

  • 如果开关使用的常数是相邻的,最好是从0到n,则可以用函数指针跳转表替换整个开关。现代编译器应该做到这一点,但较旧的编译器可能会遇到困难
  • 虽然这里需要浮点运算,但这并不明显,因为您将结果强制转换为int。用整数运算替换浮点运算可能会大大提高性能,尤其是在缺少FPU的微控制器系统等上。如果浮点数的唯一目的是圆除法,则考虑