gcc是否以代数方式优化c ++代码?如果可以,优化程度如何? [英] Does gcc optimize c++ code algebraically and if so to what extent?

查看:70
本文介绍了gcc是否以代数方式优化c ++代码?如果可以,优化程度如何?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下代码,其中显示了一些简单的算术运算

Consider the following piece of code showing some simple arithmetic operations

    int result = 0;

    result = c * (a + b) + d * (a + b) + e;

要在cpu上方的表达式中获得结果,将需要执行两个整数乘法和三个整数加法.但是从代数上讲,上面的表达式可以简化为下面的代码.

To get the result in the expression above the cpu would need to execute two integer multiplications and three integer additions. However algebraically the above expression could be simplified to the code below.

 result = (c + d) * (a + b) + e

两个表达式在代数上是相同的,但是第二个表达式仅包含一个乘法和三个加法. gcc(或与此相关的其他编译器)是否能够自行进行此简单的优化.

The two expressions are algebraically identical however the second expression only contains one multiplication and three additions. Is gcc (or other compilers for that matter) able to make this simple optimization on their own.

现在假设编译器足够智能,可以进行简单的优化,那么它是否能够优化更复杂的内容,例如梯形规则(用于数值积分).下面的示例以pi/4的步长(为简单起见较小)来近似sin(x)下的区域,其中0 <= x <= pi.请假定所有文字都是运行时变量.

Now assuming that the compiler is intelligent enough to make this simple optimization, would it be able to optimize something more complex such as the Trapezoidal rule (used for numerical integration). Example below approximates the area under sin(x) where 0 <= x <= pi with a step size of pi/4 (small for the sake of simplicity). Please assume all literals are runtime variables.

#include <math.h>

// Please assume all literals are runtime variables. Have done it this way to 
// simplify the code.
double integral = 0.5 * ((sin(0) + sin(M_PI/4) * (M_PI/4 - 0) + (sin(M_PI/4) + 
    sin(M_PI/2)) * (M_PI/2 - M_PI/4) + (sin(M_PI/2) + sin(3 * M_PI/4)) * 
    (3 * M_PI/4 - M_PI/2) + (sin(3 * M_PI/4) + sin(M_PI)) * (M_PI - 3 * M_PI/4));

现在,可以使用梯形法则将上述函数简化为这样的形式.这样可以大大减少获得相同答案所需的乘法/除法次数.

Now the above function could be written like this once simplified using the trapezoidal rule. This drastically reduces the number of multiplications/divisions needed to get the same answer.

integral = 0.5 * (1 / no_steps /* 4 in th case above*/) * 
    (M_PI - 0 /* Upper and lower limit*/) * (sin(0) + 2 * (sin(M_PI/4) +
    sin(3 * M_PI/4)) + sin(M_PI));

推荐答案

GCC(以及大多数C ++编译器)不会重构代数表达式.

GCC (and most C++ compilers, for that matter) does not refactor algebraic expressions.

这主要是因为就GCC和通用软件算法而言,这些行

This is mainly because as far as GCC and general software arithmetic is concerned, the lines

double x = 0.5 * (4.6 + 6.7);
double y = 0.5 * 4.6 + 0.5 * 6.7;

assert(x == y); //Will probably fail!

不保证将其评估为完全相同的数字.没有这样的保证,海湾合作委员会就无法优化这些结构.

Are not guaranteed to be evaluate to the exact same number. GCC can't optimize these structures without that kind of guarantee.

此外,操作顺序可能很重要.例如:

Furthermore, order of operations can matter a lot. For example:

int x = y;
int z = (y / 16) * 16;

assert(x == z); //Will only be true if y is a whole multiple of 16

从代数上讲,这两行应该相等,对吗?但是,如果yint,则实际上将使x等于"y舍入为16的较低整数倍".有时,这是预期的行为(例如,如果您要进行字节对齐).其他时候,这是一个错误.重要的是,两者都是有效的计算机代码,并且都可以根据情况使用,并且如果GCC围绕这些结构进行了优化,则将阻止程序员对其代码进行代理.

Algebraically, those two lines should be equivalent, right? But if y is an int, what it will actually do is make x equal to "y rounded to the lower whole multiple of 16". Sometimes, that's intended behavior (Like if you're byte aligning). Other times, it's a bug. The important thing is, both are valid computer code and both can be useful depending on the circumstances, and if GCC optimized around those structures, it would prevent programmers from having agency over their code.

这篇关于gcc是否以代数方式优化c ++代码?如果可以,优化程度如何?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆