- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在寻找相关的性能指标来基准测试和优化我的C / C ++代码。例如,虚拟内存使用率是一个简单但有效的指标,但我知道有些虚拟内存使用情况更为专业,可以帮助优化特定域:缓存命中/未命中,上下文切换等。
我相信这里是一个列出性能指标,衡量指标以及如何衡量指标的好地方,以帮助希望开始优化程序的人员知道从何开始。
最佳答案
时间是最相关的指标。
这就是为什么大多数分析器默认使用测量/采样时间或核心时钟周期的原因。了解代码在何处花费时间是寻找加速的重要第一步。首先找出缓慢的原因,然后找出为什么缓慢。
您可以找到2种根本上不同的加速方式,时间会帮助您找到它们。
算法上的改进:首先找到减少工作量的方法。这通常是最重要的一种,而Mike Dunlavey的回答集中于此。您绝对不应忽略这一点。缓存重新计算速度很慢的结果非常值得,特别是如果速度足够慢以至于从DRAM加载仍然更快。
在这两种加速之间,使用可以更有效地解决实际CPU问题的数据结构/算法。 (例如,实际上链表通常比数组慢,因为指针追赶延迟是一个瓶颈,除非您最终过于频繁地复制大型数组...)
更有效率地使用蛮力以更少的周期完成相同的工作。 (和/或对程序的其余部分更友好,具有较小的缓存占用空间和/或较少的分支,占用了分支预测变量中的空间,等等。)
通常需要更改数据布局以使其更易于缓存,和/或使用SIMD手动矢量化。或者以更聪明的方式这样做。或编写一个处理普通特殊情况的函数要比普通情况下的函数快。甚至牵手编译器为您的C源代码制作更好的asm。
考虑对现代x86-64上的float
数组求和:从延迟绑定的标量添加到具有多个累加器的AVX SIMD,可以使您加速8(每个向量元素)* 8(Skylake的延迟/吞吐量)= 64x对于中等大小的阵列(仍在单个内核/线程上),在理论上最好的情况下,您不会遇到另一个瓶颈(例如,如果您的数据在L1d缓存中不热,则为内存带宽)。 Skylake vaddps
/ vaddss
具有4个周期延迟,并且每2时钟= 0.5c互惠吞吐量。 (https://agner.org/optimize/)。 Why does mulss take only 3 cycles on Haswell, different from Agner's instruction tables?有关隐藏多个FP延迟的多个累加器的更多信息。但这与将总计存储在某个地方相比仍然很困难,甚至可能在您更改元素时使用增量更新总计。 (但是,与整数不同,FP舍入误差会以这种方式累积。)
如果您没有看到明显的算法改进,或者想在进行更改之前了解更多信息,请检查CPU是否停滞在任何事物上,或者是否在效率上仔细考虑了编译器所做的所有工作。
每时钟指令数(IPC)告诉您CPU是否接近其最大指令吞吐量。 (或更准确地说,x86上每个时钟发出的融合域uops,因为例如一个rep movsb
指令是一个很大的存储器,并解码为许多uops。cmp/ jcc从2条指令融合到1 uop,从而增加了IPC,但是管道宽度仍然是固定的。)
每条指令完成的工作也是一个因素,但是您不能使用探查器来衡量:如果您有专门知识,请查看编译器生成的asm,以查看用更少的指令进行相同的工作是否可行。如果编译器没有自动矢量化或效率低下,则根据问题,通过使用SIMD内部函数手动矢量化,您可能会为每条指令完成更多工作。或通过调整C源代码以使汇编语言自然地进行处理,从而使编译器能够发出更好的汇编语言。例如What is the efficient way to count set bits at a position or lower?。并参见C++ code for testing the Collatz conjecture faster than hand-written assembly - why?
如果发现IPC较低,请通过考虑诸如高速缓存未命中或分支未命中或较长的依赖链之类的可能性(通常是由于前端或内存没有瓶颈而导致IPC较低的原因)来找出原因。
或者,您可能会发现它已经接近最佳地应用CPU的可用蛮力了(不太可能,但是对于某些问题可能)。在那种情况下,您唯一的希望是改进算法以减少工作量。
(CPU频率不是固定的,但是核心时钟周期是一个很好的代理。如果您的程序没有花时间等待I / O,则测量核心时钟周期可能更有用。)
多线程程序的大部分串行部分可能很难检测到;当其他线程被阻塞时,大多数工具没有一种使用循环来查找线程的简便方法。
但是,花费在函数上的时间并不是唯一的指标。一个函数可以通过触摸大量内存来使程序的其余部分变慢,从而导致从缓存中逐出其他有用数据。因此,这种效果是可能的。或者某个地方有很多分支可能会占用CPU的某些分支预测能力,从而导致其他地方出现更多分支未命中的情况。
但是请注意,在大型代码库中,包含热点的函数可以有多个调用者,仅查找CPU在哪里花费大量时间执行并不是最有用的。例如在memcpy中花费大量时间并不意味着您需要加快memcpy的速度,这意味着您需要找到哪个调用方经常调用memcpy。依此类推,备份呼叫树。
使用可以记录堆栈快照的探查器,或者仅在调试器中按Control-C并几次查看调用堆栈。如果某个函数通常出现在调用堆栈中,则说明正在进行昂贵的调用。
相关:linux perf: how to interpret and find hotspots,尤其是Mike Dunlavey在这里的回答说明了这一点。
从根本上避免进行工作的算法改进通常比更有效地完成相同工作更有价值。
但是,如果您发现某些工作的IPC值很低,您还没有想出如何避免的方法,那么一定要看一下如何重新安排数据结构以更好地进行缓存,或者避免分支预测错误。
或者,如果高IPC仍需要很长时间,则手动向量化循环可能会有所帮助,每条指令执行4倍或更多的工作。
关于performance - 与C/C++最相关的性能指标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55650592/
第一段代码工作正常,并给出了我需要的结果。我现在想做的是让它在 'as num' 上返回 3 个数字值对于“as num”上的 3 个不同值,对于同一列上的 3 个不同位置 SELEC
我想分析一些数据以编写定价算法。以下日期可用: 我需要三个变量/维度的函数/相关因子,它显示三个维度(pers_capacity、卧室数量、浴室数量)增长时中位数(价格)的变化。例如Y(#pers_c
正如标题所说 - 我的 Sprite Kit 游戏时不时地在后台崩溃,总是出现此错误 - Exception Type: EXC_BAD_ACCESS (SIGSEGV) Exception Sub
假设我尝试保存以下数据,并且Songs模型的name属性上设置了Phalcon \ Mvc \ Model \ Validator \ PresenceOf验证器 // Get an existing
我有一个 if 控件,如下所示; if (Directory.Exists(System.IO.Path.Combine(systemPath, "Reports", companyName))
有人可以告诉我我们使用 ReadLine() 从文件 (.txt) 中读取特定行吗?现在我想读取文件的全部内容(不仅仅是第一行)。为此我需要使用什么方法。我用谷歌搜索了很多,但找不到解决方案。 我的代
我相信在大学时我用从 C 派生的语言为 FPGA 编写了一个程序。我了解 VHDL 和 verilog 等语言。但是,我不明白的是程序员在使用哪个方面有多少选择?它依赖于FPGA吗?我将使用 Xili
我有一个 if 控件,如下所示; if (Directory.Exists(System.IO.Path.Combine(systemPath, "Reports", companyName))
如何在运行时更改 Dashcode (Javascript) 中图像对象的源? 我试过: var image = document.getElementById("image").object;ima
我有几个相互关联的类,它们将被多种不同的算法使用 例子: struct B; struct A { B* parent; }; struct B { std::vector child
我正在开发一个网站,用户在客户收到的表中输入金额,如果任何客户没有提供分期付款(金额),则用户不会在表中输入任何金额,并且用户希望获取违约者的信息客户以10天为基础。所以我的问题是应该定义什么表和属性
我试图从上一个条目中选择一个值,并每次将该数字加一。我让它工作到选择当前条目值(默认 1000)并递增 1 并重新插入该值(因此每次最终都是 1001)。我需要它来选择该字段的最后一个条目,这样它将变
我不擅长“制作”查询。假设这是我的数据库: artist pics ------------------- -
最近,我要为我的网站做一个即时通知系统。我听说 COMET 在这种情况下必不可少。 我已经搜索 PHP 和 Comet 一段时间了,但是,我发现的指南和文章似乎只是循环中的 ajax 请求。例如,有一
我正在开发一款 iOS 游戏,我希望 clown 在场景外生成,然后向下移动。我的想法是全部创建它们,并将它们以 360 像素的距离放置在不可见的场景中。 像这样: SKSpriteNode *clo
我有以下子订单表。 mysql> select * from suborder; +-------------+------------------+ | order_state | bookin
这可能是一个有点初学者的问题,但考虑到在 Java 中调试编码是相当相关的:什么时候编码与 String 对象相关? 假设我有一个要保存到文件中的字符串对象。 String 对象本身是否使用某种我应该
首先我想说我是 CPP 的新手(我从 cpp11 开始):)考虑以下实体:学生(名字+姓氏)和组(描述+更多学生)。我在 C++ 中创建了以下 2 个类: class Student { privat
我正在尝试在单击该复选框时同步更新我的数据库。我决定使用 aJax,但它似乎无法识别 ajax。 代码:将成为 Switch_Active(this.id) 函数的元素 ... Deactivat
我正在创建一个菜单。菜单如下。 $('.category').mouseover(function() { $(this).removeClass('category').addClass('cate
我是一名优秀的程序员,十分优秀!