我有两个不同的程序来解决用C ++编写的数学问题(程序A
和B
)。
A
执行的轮次比B
好10倍(就持续时间而言)。现在我通过valgrind工具callgrind计算了执行的CPU指令,并意识到程序A
只需要程序B
执行的指令的1/3。我原以为这个因素是1/10左右。
我知道CPU指令需要更多的CPU周期(比如内存访问),但是设计A
应该包含比B
更多的昂贵指令。
另外我不知道callgrind如何计算这些指令(在文档中找不到任何相关内容)。
任何人都可以对这种行为给出合理的解释吗? TIA
A
需要的内存远远超过B
。 答案 0 :(得分:1)
您也没有指定运行该平台的平台,每个CPU都有自己的一套“不做/不做”。
例如,在x86上,指令数与总执行时间之间的相关性非常小,如下:
std::vector<int>
对于~100k项目随机插入/删除比列表快得多,尽管向量inser / remove是O(n ^ 2) ),而list只是O(n)。 CPU手的唯一内存是L0缓存,L1就像在街上,L2就像是去其他城市,L3不同的国家。记忆本身就像月亮一样。正如您所看到的,在极端情况下,x86 CPU甚至可以执行具有~200条指令的代码+处理30倍以上的内存,与具有~10条指令的不同例程一样快。在角落的情况下,差异可能非常极端,人类很难通过阅读来源来想象。这就是为什么在x86上验证代码优化的唯一有效方法是使用足够接近实际数据的数据来分析代码。 &#34;优化&#34;只是通过理论,大写符号和&#34;直觉和#34;可以很容易地适得其反,10-20y有效,即便如此,我们用工具来分析结果,以验证收益。
当然,更大量的指令本身可以更容易从缓存中脱落,使得指令读取停止,但如果你可以创建更好的数据结构,那么甚至30kiB对1kiB的代码也是合理的(尽管它有很多风险)在被OS中断时缓存未命中。)
callgrind网站说:&#34;可选地,缓存模拟和/或分支预测(类似于Cachegrind)可以产生关于应用程序的运行时行为的进一步信息。&#34; ,所以你可以得到比指令数更精细的数据,看看是否存在一些瓶颈,重组代码/数据会使它停滞不前。