Linux perf
和GPerfTools pprof
在这段代码中给了我很多停滞的前端和后端周期:
for(j = oL; j < oR; j++) {
T[j].v = (T[j].x / div)*K+T[j].y /div;
T[j].x = T[j].x % div;
T[j].y = T[j].y % div;
counterK[T[j].k]++;
}
给了我:
9.973.660.617 stalled-cycles-frontend # 42,16% frontend cycles idle
4.874.722.502 stalled-cycles-backend # 20,60% backend cycles idle
我理解停滞的循环意味着指令管道无法真正前进,等待(可能)来自内存的某些数据。我可以看到在这段代码中有很多解构引用的构造成员,这可能是一个问题,但我担心我缺乏足够的知识来看到那里的任何优化。有人可以帮忙吗?
答案 0 :(得分:1)
解除引用struct
指针本身不应该是现代架构的问题。他们可以做相对寻址并很好地应对这种访问。另外,如一条评论中提到的别名不应该是一个问题。 *T
和*counterK
有不同的类型,因此C永远不会假设它们是别名。
通常,对于这样的循环,因为您向我们展示了处理器/内存带宽是bottelneck而不是处理器的速度。可能是,你正处于你的记忆可以服务的极限。
您正在按顺序访问T
,这已经是您可以做的最好的了。 T
可能唯一的优化就是你有很多字段,而你正在向我们显示的循环没有使用这些字段。那么你可能会浪费处理器/内存带宽。然后压缩一个只有所需信息的数组中的东西可能会有所帮助。
对于counterK
,事情更复杂,因为您提供的信息没有提示访问模式或数组的大小。如果counterK
很大(比你的L1缓存大得多)并且你的访问非常不规则,那么这些摊位可能来自这里。