返回信息流void func()
{
for (int i = 0; i < M; i ++)
for (int j = 0; j < N; j ++)
m[i][j] += m[i][j];
}
会被O3优化掉吗?把m[i][j] += m[i][j]改成m[i][j] += m[i][j] * m[i][j]...在O3下运行时间不变。
如果在函数结尾return任意m[a][b]的话,还会被优化掉吗?
这是一条镜像帖。来源:北邮人论坛 / cpp / #72297同步于 2013/7/2
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖
GCC的O3优化会怎么优化这个循环
puerxun
2013/7/2镜像同步9 回复
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
发现m[i][j]与m[j][i]速度差很多,因为内存里面m是按照行来保存的。前面那个位置计算只要++,后面要j*N+i。但是不是存在其他的优化使得他们速度差很多呢,比如cache?
【 在 nuanyangyang 的大作中提到: 】
: 不会。m看上去不是局部变量。
发现m[i][j]在O3的时候会被一个叫做rename-register的策略优化,这个策略神码意思哇?
【 在 nuanyangyang 的大作中提到: 】
: 不会。m看上去不是局部变量。
寄存器重命名~用来展开已知的循环体实现指令多发射~
【 在 puerxun 的大作中提到: 】
: 发现m[i][j]在O3的时候会被一个叫做rename-register的策略优化,这个策略神码意思哇?
:
如果m是类或者在一个小型子函数中,是否还能这么优化捏?
【 在 tonyjansan 的大作中提到: 】
: 寄存器重命名~用来展开已知的循环体实现指令多发射~
:
【 在 puerxun 的大作中提到: 】
: 发现m[i][j]与m[j][i]速度差很多,因为内存里面m是按照行来保存的。前面那个位置计算只要++,后面要j*N+i。但是不是存在其他的优化使得他们速度差很多呢,比如cache?
:
这个我的理解是:行++,跟列的j*N+i都是O(1)的时间复杂度,但是根据时间局部性,CPU在从存储器拉数据的时候,并不是单个字节拉取,而是一块拉取,所以m[k+1]跟m[k]都处于cache中,cache命中,但是m[j*N+k] m[k]很有可能不在同一个缓存行中,所以miss;数量级会相差几十个。
我也觉得cache命中是重要原因,因为那个加法和乘法在时间上实在太微不足道了。但假设m[i][j]被函数调用或者被用在一个较为复杂的过程中,这时候cache就要腾出来给其他东西吧,这个cache命中的优化就失效了?
【 在 JacKie575 的大作中提到: 】
: 这个我的理解是:行++,跟列的j*N+i都是O(1)的时间复杂度,但是根据时间局部性,CPU在从存储器拉数据的时候,并不是单个字节拉取,而是一块拉取,所以m[k+1]跟m[k]都处于cache中,cache命中,但是m[j*N+k] m[k]很有可能不在同一个缓存行中,所以miss;数量级会相差几十个。
【 在 puerxun 的大作中提到: 】
: 我也觉得cache命中是重要原因,因为那个加法和乘法在时间上实在太微不足道了。但假设m[i][j]被函数调用或者被用在一个较为复杂的过程中,这时候cache就要腾出来给其他东西吧,这个cache命中的优化就失效了?
:
那未必,因为存储器中同一个作用域的变量都是相邻存放的。即使变量很多,那么在从存储器拉取块的时候,有可能只需要有限的几次拉取就能将很多变量读取到cache中。现代处理器中,除非代码写的很不友好,否则缓存命中率大概在80以上。有本书介绍cache的,计算机组成与体系结构,有说道这个。