
文章插图
大家可以稍微看一眼这个小例子 , 我们想测试的是memset的性能 , 左边是memset , 右边是一个简单的 for 循环来进行清理 , 我们循环若干次 , 想看最后这两个clock减一下 , 得出我们输出执行时间的差异 。

文章插图
可以看到在O0的情况下 , memset比手工循环要快出50倍以上 , memset 似乎比较快 , O1 这个比值就减少了 , O1、O0零是不是更接近真实呢?再看O2 , 会发现出了一个很奇怪的鬼 , memset比手工循环慢了10万倍 , 第一次碰到这个问题肯定就是满头雾水了 , 原因很简单:对 buffer 的写入被优化掉了 。如果你出现了memset 比手工循环慢 , 那可能的原因就是 memset 没有被优化掉 , 把手工循环完全被优化没了 。我们有时候就会想到 volatile 能不能帮助解决这个问题 。

文章插图
这是个执行结果 , 我们可以看一下 , 看起来似乎正常一点 , 加入 volatile 之后我们会发现 O1 和 O2的结果一致了 , 都是memset大概是手工循环的性能的5倍 , 这是不是最后的结果呢?还不是 。因为 volatile 本身会妨碍优化 。

文章插图
我们可以看一下 , 同样是手工循环写入 , 一个是有 volatile , 一个是没有 volatile , 然后我们看一下汇编 , 对于有 volatile 的我们发现汇编里面编译器产生的这个代码就是很老实的 , 一次写一个字节 , 一共循环80次 , 写入到内存里面去 , 就这么简单 , 右边这个代码就不一样了 , 我们会发现编译器连循环都没有了 , 直接一次写16个字节 , 连续展开写五次结束 , 很明显右边这个代码的执行性能肯定比左边的高 , 这是可以想象的一件事 。

文章插图
所以我们测试的角度来讲就一定要防优化 , 有时候我们要让编译器不要做一些不必要的优化 , volatile 是得谨慎使用 , 它确实可以防止优化 , 但有时会防止得过头 , 而且它虽然能够防止编译器的重排序 , 但防止不了处理器的重排序 。使用全局变量肯定是有好处的 , 你往全局变量里写一定会写入 , 如果往本地变量里写 , 那编译器有可能就把这个东西完全优化 。还有用锁可以当简单的内存屏障 , 这是比较可靠的 C++ 内存模型 , 能保证在这种情况下性能是令人满意的 , 但用锁的话性能开销就会比较大 , 时间会比较大 , 我们还可以使用 noinline 来防止一般的内联 。但不管怎么样 , 我们可以发现如果把这些东西组合在一起 , 我们测试精度就需要提高 , 用clock 实际上是有点问题的 , 特别在Windows下它的精度太低了 , 应该只有1毫秒的精度 。

文章插图
在 Linux 下 clock 的精度稍微高一点 , 能达到1微秒 , 但我测过一个结果 , 它的耗时比较大 。实际上我们可以看一下这里面 , 最优选的 , 在 Intel 平台上应该是个叫 rdtsc 的一条指令 , 它一般有内联汇编 , 可以直接使用 rdtsc 这个函数 , 精度达到了 10 纳秒 , 比其他的都要高 , 开销也要低一点 。如果你没有 rdtsc , 就可以考虑系统里面提供的 system_clock , steady_clock , high_resolution_clock 三个 C++ 里带来的时钟 。我一般会推荐 steady_clock , 因为它能够保证时钟是稳定的 , 保证你测试的过程中不会因为有某个进程进行系统的对时之类的操作 , 发生时间反转之类的情况 。利用这些东西 , 我们实际上就可以测出比较高精度的结果 。
- 美甲培训学校如何
- 服装设计培训 服装设计师培训学校
- 学会计 会计培训学校机构
- 英语口语培训 口语培训课程
- 影视摄影师培训学校
- 职业培训 深圳职业培训学校
- 装饰培训机构 装饰设计培训哪里好
- sigill sigikid
- 广州美容学校推荐 广州美甲培训学校地址
- 西安计算机培训机构哪个最好 西安计算机培训学校有哪些
特别声明:本站内容均来自网友提供或互联网,仅供参考,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
