如何防止时间戳被重新排序
How to prevent timestamp from being reorder out?
我的理解是c++允许任何非IO或外部函数调用的东西都可以优化重新排序。这开始使我在编写RAII风格的时间戳函数时感到沮丧。
编辑
这是一个独立的例子,
VS 2012的代码,带有优化
#include <chrono>
#include <iostream>
#include <atomic>
#include <string>
using namespace std;
class TimeSlice
{
public:
TimeSlice(std::string myname): name(myname), start(timestamp())
{
fency();//don't optomize me out!
}
~TimeSlice()
{
fency();
auto elapsed = timestamp()-start;
cout << name<<(int) elapsed << endl;
}
static inline long long timestamp()
{
return chrono::duration_cast<chrono::milliseconds>(chrono::system_clock::now().time_since_epoch()).count();
}
private:
const long long start;
const std::string name;
static inline void fency()
{
std::atomic_signal_fence(std::memory_order_seq_cst);
}
};
函数调用没有被优化,它们被重新排序。它被编译为:
_sleep(10);
start = timestamp();
elapsed = timestamp()-start;
cout << name<<(int) elapsed << endl;
这个重排序是合法的,因为_sleep和timestamp都不构成IO。如果支持c++11,可以使用信号处理程序内存栅栏来防止这种重新排序。只需包含并插入:
std::atomic_signal_fence(std::memory_order_seq_cst);
放在析构函数和构造函数体的开头。对于x86_&4上的GCC 4.7和4.8,这样的内存栅栏不会产生任何代码,只是约束编译器重新排序。
我不认为c++优化器实际上是这里的问题。更有可能的是,问题是您试图测量的时间量在某些情况下小于您正在使用的时钟的最小粒度——也就是说,timestamp()在TimeSlice构造函数和析构函数中返回相同的值,因为第二次调用在第一次调用之后执行得如此之快,以至于时钟值没有足够的时间增加下一个滴答量。
如果是这种情况,那么解决方案将是找到一个更高精度的时钟API来使用,或者测量更长的事件(例如,做一个10000次迭代的循环操作并测量它),或者仅仅接受这样的理解,即非常小的时间增量可能会被时钟的tick-granularity有效地舍入到零。
相关文章:
- 合并排序不排序自创建数组类 c++
- 使用 Key 对 C++ 中的哈希映射进行排序. 无法排序
- std::排序为排序自定义对象时出现的向量引发错误
- 队列快速排序不排序和打印随机字符串[C ]
- 插入排序中途排序
- C 排序无法排序一组字符串
- C 选择排序不排序
- 气泡排序不排序
- C++:使用 LSD 基数排序字符串排序崩溃
- C 样式的字符串排序与排序和 qsort
- C++ 快速排序不排序
- 如何对包含 pair<int,int> 元素的向量进行排序?排序是根据比较功能完成的
- Introsort(快速排序+堆排序)实现和复杂性
- 用于排序/操作/排序的最佳替代算法
- 没有严格弱排序的排序集
- STL:指针关联排序容器:排序谓词模板
- 排序和排序有什么区别?
- 寻找c++快速排序/插入排序组合中的错误
- 创建没有重复项的新排序向量
- 冒泡排序不排序最后一个数字与此算法