同时创建的对象 - 不需要的编译器优化?
Objects created at the same time - unwanted compiler optimization?
我遇到了一个奇怪的问题:
for (size_t i=0; i<20; i++)
{
// pre is a vector<UserType>
pre.push_back(UserType()); // In UserType constructor, record std::chrono::steady_clock::now()
}
给出以下对象
(gdb) print pre = std::vector of length 20, capacity 32 =
{{timePoint_ = {__d = {__r = 1427724945979761000}}}, {
timePoint_ = {__d = {__r = 1427724945979761000}}}, {timePoint_ = {__d = {
__r = 1427724945979761000}}}, {timePoint_ = {__d = {__r = 1427724945979761000}}}, {
timePoint_ = {__d = {__r = 1427724945979761000}}}, {timePoint_ = {__d = {
__r = 1427724945979761000}}}, {timePoint_ = {__d = {__r = 1427724945979761000}}}, {
timePoint_ = {__d = {__r = 1427724945979761000}}}, {timePoint_ = {__d = {
__r = 1427724945979761000}}}, {timePoint_ = {__d = {__r = 1427724945979761000}}}, {
timePoint_ = {__d = {__r = 1427724945979761000}}}, {timePoint_ = {__d = {
__r = 1427724945979761000}}}, {timePoint_ = {__d = {__r = 1427724945979761000}}}, {
timePoint_ = {__d = {__r = 1427724945979761000}}}, {timePoint_ = {__d = {
__r = 1427724945979761000}}}, {timePoint_ = {__d = {__r = 1427724945979761000}}}, {
timePoint_ = {__d = {__r = 1427724945979761000}}}, {timePoint_ = {__d = {
__r = 1427724945979761000}}}, {timePoint_ = {__d = {__r = 1427724945979761000}}}, {
timePoint_ = {__d = {__r = 1427724945979761000}}}}
1,理论上,这 20 个 UserType 对象中的每一个都应该具有不同且唯一的 time_since_epoch().count(),但在 gdb 输出中,它们都是相同的。
2,我在这里尝试了相同的代码:http://melpon.org/wandbox 并且每个对象都有一个唯一的时间戳。所以我正在观察不同的行为。
3、一些分析:UserType() in pre.push_back(UserType());是右值;然后编译器将右值值复制(通过复制构造函数)到向量 pre 中的左值对象中。编译器是否有可能看到常量循环号 20 和右值对象指令,因此决定创建 20 对象 "at the same time" 作为优化?即使是这种情况,编译器也不太可能同时进行所有构造 - 没有同时进行的事情 - 只有可以忽略的小差异。我不认为编译器可以在 steady_clock.
的 1 个滴答内完成 20 个对象构造
4,这是我的 Makefile 中的相关编译标志 - 请注意,我没有要求编译器进行优化:-g -Wall -std=gnu++0x
5,这段代码(20个对象构造的循环)在google测试文件中;我的编译器是 cygwin 上的 g++ 4.8.3。
我的问题是:
这是怎么回事?具体来说,为什么我看到构建 20 个对象的时间戳相同?
非常感谢。
/*******************根据请求,UserType 实现********************* **/
class UserType
{
public:
UserType()
{
timePoint_ = std::chrono::steady_clock::now();
}
bool operator==(const UserType other) const
{
return timePoint_ == other.timePoint_;
}
friend std::ostream& operator<<(std::ostream& out, UserType type);
protected:
std::chrono::time_point<std::chrono::steady_clock> timePoint_;
};
std::ostream& operator<<(std::ostream& out, UserType type)
{
out << type.timePoint_.time_since_epoch().count() << std::endl;
return out;
}
std::chrono::steady_clock::now()
不保证任何特定分辨率。它只保证单调性。因此连续调用 可以 return 同时。事实上,为了满足单调性要求,可能会牺牲分辨率。
如果您想要尽可能高分辨率的时钟,则必须使用 std::chrono::high_resolution_clock
。
std::chrono::steady_clock::period
将使用 std::ratio
.
告诉您以秒为单位的刻度长度
我想我已经解决了问题:我将 20 次构造函数调用延长到 2000 次,然后我开始观察不同的构造时间戳。也就是说,在 1 纳秒内进行了数百次构造函数调用。这太棒了。
我遇到了一个奇怪的问题:
for (size_t i=0; i<20; i++)
{
// pre is a vector<UserType>
pre.push_back(UserType()); // In UserType constructor, record std::chrono::steady_clock::now()
}
给出以下对象
(gdb) print pre = std::vector of length 20, capacity 32 = {{timePoint_ = {__d = {__r = 1427724945979761000}}}, { timePoint_ = {__d = {__r = 1427724945979761000}}}, {timePoint_ = {__d = { __r = 1427724945979761000}}}, {timePoint_ = {__d = {__r = 1427724945979761000}}}, { timePoint_ = {__d = {__r = 1427724945979761000}}}, {timePoint_ = {__d = { __r = 1427724945979761000}}}, {timePoint_ = {__d = {__r = 1427724945979761000}}}, { timePoint_ = {__d = {__r = 1427724945979761000}}}, {timePoint_ = {__d = { __r = 1427724945979761000}}}, {timePoint_ = {__d = {__r = 1427724945979761000}}}, { timePoint_ = {__d = {__r = 1427724945979761000}}}, {timePoint_ = {__d = { __r = 1427724945979761000}}}, {timePoint_ = {__d = {__r = 1427724945979761000}}}, { timePoint_ = {__d = {__r = 1427724945979761000}}}, {timePoint_ = {__d = { __r = 1427724945979761000}}}, {timePoint_ = {__d = {__r = 1427724945979761000}}}, { timePoint_ = {__d = {__r = 1427724945979761000}}}, {timePoint_ = {__d = { __r = 1427724945979761000}}}, {timePoint_ = {__d = {__r = 1427724945979761000}}}, { timePoint_ = {__d = {__r = 1427724945979761000}}}}
1,理论上,这 20 个 UserType 对象中的每一个都应该具有不同且唯一的 time_since_epoch().count(),但在 gdb 输出中,它们都是相同的。
2,我在这里尝试了相同的代码:http://melpon.org/wandbox 并且每个对象都有一个唯一的时间戳。所以我正在观察不同的行为。
3、一些分析:UserType() in pre.push_back(UserType());是右值;然后编译器将右值值复制(通过复制构造函数)到向量 pre 中的左值对象中。编译器是否有可能看到常量循环号 20 和右值对象指令,因此决定创建 20 对象 "at the same time" 作为优化?即使是这种情况,编译器也不太可能同时进行所有构造 - 没有同时进行的事情 - 只有可以忽略的小差异。我不认为编译器可以在 steady_clock.
的 1 个滴答内完成 20 个对象构造4,这是我的 Makefile 中的相关编译标志 - 请注意,我没有要求编译器进行优化:-g -Wall -std=gnu++0x
5,这段代码(20个对象构造的循环)在google测试文件中;我的编译器是 cygwin 上的 g++ 4.8.3。
我的问题是:
这是怎么回事?具体来说,为什么我看到构建 20 个对象的时间戳相同?
非常感谢。
/*******************根据请求,UserType 实现********************* **/
class UserType
{
public:
UserType()
{
timePoint_ = std::chrono::steady_clock::now();
}
bool operator==(const UserType other) const
{
return timePoint_ == other.timePoint_;
}
friend std::ostream& operator<<(std::ostream& out, UserType type);
protected:
std::chrono::time_point<std::chrono::steady_clock> timePoint_;
};
std::ostream& operator<<(std::ostream& out, UserType type)
{
out << type.timePoint_.time_since_epoch().count() << std::endl;
return out;
}
std::chrono::steady_clock::now()
不保证任何特定分辨率。它只保证单调性。因此连续调用 可以 return 同时。事实上,为了满足单调性要求,可能会牺牲分辨率。
如果您想要尽可能高分辨率的时钟,则必须使用 std::chrono::high_resolution_clock
。
std::chrono::steady_clock::period
将使用 std::ratio
.
我想我已经解决了问题:我将 20 次构造函数调用延长到 2000 次,然后我开始观察不同的构造时间戳。也就是说,在 1 纳秒内进行了数百次构造函数调用。这太棒了。