【发布时间】:2015-09-29 13:12:30
【问题描述】:
我最近阅读了std::move 如何通过移动值而不是复制它们来加速代码。所以我做了一个测试程序来比较使用std::vector的速度。
代码:
#include <iostream>
#include <vector>
#include <stdint.h>
#ifdef WIN32
#include <Windows.h>
#else
#include <sys/time.h>
#include <ctime>
#endif
#undef max
// Returns the amount of milliseconds elapsed since the UNIX epoch. Works on both
// windows and linux.
uint64_t GetTimeMs64()
{
#ifdef _WIN32
// Windows
FILETIME ft;
LARGE_INTEGER li;
// Get the amount of 100 nano seconds intervals elapsed since January 1, 1601 (UTC) and copy it
// to a LARGE_INTEGER structure.
GetSystemTimeAsFileTime(&ft);
li.LowPart = ft.dwLowDateTime;
li.HighPart = ft.dwHighDateTime;
uint64_t ret = li.QuadPart;
ret -= 116444736000000000LL; // Convert from file time to UNIX epoch time.
ret /= 10000; // From 100 nano seconds (10^-7) to 1 millisecond (10^-3) intervals
return ret;
#else
// Linux
struct timeval tv;
gettimeofday(&tv, NULL);
uint64 ret = tv.tv_usec;
// Convert from micro seconds (10^-6) to milliseconds (10^-3)
ret /= 1000;
// Adds the seconds (10^0) after converting them to milliseconds (10^-3)
ret += (tv.tv_sec * 1000);
return ret;
#endif
}
static std::vector<std::string> GetVec1()
{
std::vector<std::string> o(100000, "abcd");
bool tr = true;
if (tr)
return std::move(o);
return std::move(std::vector<std::string>(100000, "abcd"));
}
static std::vector<std::string> GetVec2()
{
std::vector<std::string> o(100000, "abcd");
bool tr = true;
if (tr)
return o;
return std::vector<std::string>(100000, "abcd");
}
int main()
{
uint64_t timer;
std::vector<std::string> vec;
timer = GetTimeMs64();
for (int i = 0; i < 1000; ++i)
vec = GetVec1();
std::cout << GetTimeMs64() - timer << " timer 1(std::move)" << std::endl;
timer = GetTimeMs64();
for (int i = 0; i < 1000; ++i)
vec = GetVec2();
std::cout << GetTimeMs64() - timer << " timer 2(no move)" << std::endl;
std::cin.get();
return 0;
}
我得到了以下结果:
释放 (x86) /O2。 tr = true
4376 计时器 1(std::move)
4191 定时器 2(不动)
释放 (x86) /O2。 tr = false
7311 定时器 1(std::move)
7301 定时器 2(不动)
两个计时器之间的结果非常接近,并且差别不大。我已经假设这是因为 返回值优化 (RVO) 这意味着我的值返回值已经在我不知情的情况下被编译器移动了,对吧?
然后我运行了没有任何优化的新测试,以确保我是对的。 结果:
发布 (x86) /Od。 tr = true
40860 定时器 1(std::move)
40863 定时器 2(不动)
发布 (x86) /Od。 tr = false
83567 定时器 1(std::move)
82075 定时器 2(不动)
现在,即使 /O2 和 /Od 之间的差异非常显着,但 no move 或 std::move(甚至 tr 是 true 或 false)之间的差异很小。
这是否意味着即使禁用了优化,编译器也可以应用RVO 还是std::move 没有我想象的那么快?
【问题讨论】:
-
你看过生成的指令了吗?
-
附注:您应该查看
std::chrono::high_resolution_clock以满足您的时间需求... -
这是 12.8,第 31、32 段。
-
为了真正看到差异,请使用重对象进行复制。使用某些自定义类型的对象,该对象具有非常“昂贵”的复制构造,例如复制图像缓冲区。
标签: c++ c++11 optimization visual-studio-2015 return-value-optimization