C++ 评测:简单代码行的自时间与总时间

C++ 评测:简单代码行的自时间与总时间,c++,c,multithreading,profiling,profiler,C++,C,Multithreading,Profiling,Profiler,在分析时,我们知道“self time”指的是方法忽略其调用的函数所花费的时间,而“total time”指的是该方法及其子函数被调用的总时间 我有一个简单的函数,其中我只对数组进行计算,不调用数组中的任何其他函数。但是,在分析时,self和total的时间是完全不同的,对于函数本身以及函数上的每一行。下面是Zoom Profiler中的一条剖面线示例,它使用32个线程运行 for循环中线路的计时 Total Self Code 29.4 sec 16.9

在分析时,我们知道“self time”指的是方法忽略其调用的函数所花费的时间,而“total time”指的是该方法及其子函数被调用的总时间

我有一个简单的函数,其中我只对数组进行计算,不调用数组中的任何其他函数。但是,在分析时,self和total的时间是完全不同的,对于函数本身以及函数上的每一行。下面是Zoom Profiler中的一条剖面线示例,它使用32个线程运行

for循环中线路的计时

Total        Self         Code
29.4 sec     16.9 sec     id=*(pid); 
让我困惑的是,基于第一段,它应该意味着如果一行代码不调用任何方法,那么自花费的时间和总花费的时间应该是相同的。
对正在发生的事情有什么想法吗?

我不太担心

分析人员显示的统计数据,即使是优秀的分析人员,也必须“有一点保留”。 这些统计数据意味着,在一些包含该行代码的堆栈示例中,它不是堆栈上的最后一行代码,这很难让人相信。 更容易相信剖析器是错的。 如今,处理器的管道运行方式遥遥领先,这可能会让人相当困惑

在任何情况下,如果您分析的原因是为了找到加速,那么很难看到如何加速特定代码行。 你在寻找你能加速的东西,而不是你不能的东西

顺便说一句,我建议不要看秒或毫秒或任何绝对时间测量值,而是看分数时间-时间除以总时间。 实际加速往往占较大的比例,从5%到99%。 此外,不必担心自含时时间,如果程序的大小很大,因此堆栈样本会变深,那么堆栈样本上的非终端行(即函数调用)是加速的有利条件。 最后,不需要测量精度,因此不需要大量样本

这就是为什么很多人使用


编辑:FWIW,这就是我的意思。以下是5个随机时间堆栈示例:

---------------------------
... some calls above
... exp(4.02) ...
... some calls below
---------------------------
... some calls above
... exp(0.35) ...
... some calls below
---------------------------
... some calls above
... push_back(...) ...
...
... new ...
...
---------------------------
...
... myArray[...]
...
---------------------------
... some calls above
... exp(0.35) ...
... some calls below
---------------------------
其中三个函数在堆栈上、代码中或您可以编辑的代码中调用了
exp
,很可能来自代码中的不同位置。 这意味着您将花费大约60%的时间调用
exp
。 你不能加速这个函数,但你能不能少叫一点

现在请注意,第二个和第五个示例使用相同的数值参数调用
exp
。 (这是任何分析人员都无法告诉您的。) 这是什么意思? 这意味着大约40%的时间都在使用重复参数的
exp
调用中, 您可以通过记住以前的值或通过记忆
exp
来避免这种情况

如果你采集样本,直到你看到一些模式,你可以做些什么,你看到它两次或更多次,你有一个健康的加速。 要达到这一点所需的样本越少,加速比就越大。 然后你可以重复整个过程,直到你不能再重复了。
这是一种可靠的方法,可以获得难以匹敌的速度。

建议:1)将测试用例压缩成一个直接从
main()调用的简单函数。
:无线程,“无多余”。看看“总体”和“自我”是否更接近。2) 在与Zoom profiler不同的编译器/分析器上尝试“简化测试用例”。例如,GCC/GPROF。我猜,尽管这也被标记为C,你使用C++。编写C++的时候几乎不可能在某个地方调用一些函数。但显然,没有代码,人们只能猜测……其他两条评论是正确的。此外,我建议在反汇编级别逐步完成代码。这样,如果该行调用函数,您将看到它。我可以很容易地想象,它正在对
pid
进行一些验证检查。感谢大家提出的富有洞察力的评论和建议@paulsm4由于代码是一个更大项目的一部分,我无法基于Put to main()复制此计时,但是我可以设法使用1个线程运行,并且看到self和total时间越来越近了5.1第4.6节第2719节idi=*(pid)`@实际上它是C,Zoom说这行代码正在调用某个头文件中的线程处理函数,但是我不确定它是否是另一种方式。但是是的,有这个电话,这就是为什么它显示在总数上。虽然反汇编没有显示这样的调用,但我不确定为什么要调用它(以缓解写冲突?)