phi*_*131 5 c++ optimization function
关于 SO 上“冗余函数调用”的编译器优化有大量问题和好的答案(我不会发布链接),但是,我在 SO 上的多个相同函数调用上找不到任何内容。
假设我有这样的代码片段:
void fairlyComplexFunction(const double &angle)
{
//do stuff and call "sin(angle)" very often in here
}
Run Code Online (Sandbox Code Playgroud)
调用sin(angle)是一个相当昂贵的操作,因为在正弦的每次调用angle范围内都是一个常量,fairlyComplexFunction最终会得到相同的结果,所以只调用一次将是一个更好的方法:
void fairlyComplexFunction(const double &angle)
{
const double sineOfAngle = sin(angle);
//do stuff and use sineOfAngle very often in here
}
Run Code Online (Sandbox Code Playgroud)
编译器是否能够以任何方式检测此类内容并为我优化它,或者第二个示例是更好的方法吗?
正如评论中已经指出的,如果编译器可以检测到被调用的函数是纯函数(没有副作用,没有 i/o,...),则它可能能够优化这样的事情。
一个使用 g++ 的小例子(https://godbolt.org/g/2b3Vgg):
#include <cmath>
extern double g (double);
template <double (*F) (double)>
double f1 (double angle) {
double x = 3 * F(angle) + F(angle);
double y = F(angle) + F(angle) * F(angle);
return x + y * F(angle);
}
template double f1<sin> (double);
template double f1<g> (double);
Run Code Online (Sandbox Code Playgroud)
您对该函数f1进行了多次调用F,并且有两个实例:
std::sin- 任何理智的编译器都应该将其视为纯函数。extern不能被视为纯函数的函数的函数。如果您查看生成的程序集*:
double f1<&sin>(double):
subq $8, %rsp
call sin
...
ret
double f1<&(g(double))>(double):
subq $40, %rsp
movsd %xmm0, (%rsp)
call g(double)
movsd %xmm0, 8(%rsp)
movsd (%rsp), %xmm0
call g(double)
movsd 8(%rsp), %xmm1
mulsd .LC0(%rip), %xmm1
...
call g(double)
movsd %xmm0, 16(%rsp)
movsd (%rsp), %xmm0
call g(double)
movsd %xmm0, 24(%rsp)
movsd (%rsp), %xmm0
call g(double)
mulsd 24(%rsp), %xmm0
movsd 16(%rsp), %xmm2
...
call g(double)
mulsd 16(%rsp), %xmm0
addsd 8(%rsp), %xmm0
...
Run Code Online (Sandbox Code Playgroud)
您会看到,在 的实例化中sin,g++ 仅执行了一次函数调用 ( call sin),而在 的实例化中g,您有 6 次调用。
所以是的,编译器可能会对对纯函数的多次调用进行一些优化,但我不会依赖它**并使用显式中间变量,如第二个示例中所示。
* 我删除了大部分生成的指令,但call显示了所有指令。
**即使使用(但它可以使用)clang也不会对此进行优化。-O3-ffast-math
| 归档时间: |
|
| 查看次数: |
1709 次 |
| 最近记录: |