问题:为什么当我单独编译和链接时,函数的性能会有所不同?
首先,代码
randoms.hpp
int XORShift();
int GameRand();
randoms.cpp
static unsigned int x = 123456789;
static unsigned int y = 362436069;
static unsigned int z = 521288629;
static unsigned int w = 88675123;
int XORShift()
{
unsigned int t = x ^ (x << 11);
x = y;
y = z;
z = w;
return w = w ^ (w >> 19) ^ (t ^ (t >> 8));
}
static unsigned int high = 0xDEADBEEF;
static unsigned int low = high ^ 0x49616E42;
int GameRand()
{
high = (high << 16) + (high >> 16);
high += low;
low += high;
return high;
}
main.cpp
#include <iostream>
#include <windows.h>
#include "randoms.hpp"
using namespace std;
//Windows specific performance tracking
long long milliseconds_now() {
static LARGE_INTEGER s_frequency;
static BOOL s_use_qpc = QueryPerformanceFrequency(&s_frequency);
LARGE_INTEGER now;
QueryPerformanceCounter(&now);
return (1000LL * now.QuadPart) / s_frequency.QuadPart;
}
void main() {
const int numCalls = 100000000; //100 mil
{
cout << "XORShift..." << endl;
long long start = milliseconds_now();
for(int i=0; i<numCalls; i++)
XORShift();
long long elapsed = milliseconds_now() - start;
cout << "\tms: " << elapsed << endl;
}
{
cout << "GameRand..." << endl;
long long start = milliseconds_now();
for(int i=0; i<numCalls; i++)
GameRand();
long long elapsed = milliseconds_now() - start;
cout << "\tms: " << elapsed << endl;
}
{
cout << "std::rand..." << endl;
long long start = milliseconds_now();
for(int i=0; i<numCalls; i++)
std::rand();
long long elapsed = milliseconds_now() - start;
cout << "\tms: " << elapsed << endl;
}
}
详情
我正在使用 C++ 和 Microsoft 的“cl”编译器。我正在测试 3 个伪随机函数的性能。它们是 XORShift、GameRand 和 std::rand()。
分别构建main.cpp和randoms.cpp并使用命令链接
cl /O2 /Oi main.cpp randoms.cpp
产生以下性能结果:
XORShift...
ms: 520
GameRand...
ms: 2056
std::rand...
ms: 3800
但是,如果我忘记了标题并直接通过
包含函数#include "randoms.cpp"
无需任何链接即可编译
cl /O2 /Oi main.cpp
我得到了非常不同的性能:
XORShift...
ms: 234
GameRand...
ms: 135
std::rand...
ms: 3823
XORShift 和 GameRand 都获得了显着的加速。很奇怪的是,GameRand 从比 XORShift 慢变得更快。如何才能得到2cd测试的速度,但仍然单独编译random.cpp并链接?
** 编辑 **:
感谢 @sehe 的评论以及 @Oswald 和 @Tomasz Kłak 的回答,问题已解决。我现在正在使用命令进行编译
cl /O2 /Oi /GL main.cpp randoms.cpp
/GL 标志执行链接时间优化。我可以单独编译文件并仍然获得内联。
最佳答案
我想到了两件事。
首先,内联可能会受到影响(由于在编译调用站点 TU 时主体不可用,编译器无法内联代码)。在现代 C++ 中,内联具有巨大优化潜力(因为它经常会内联多个级别的调用,并且生成的主体经常会产生更有趣的优化)。
现在许多编译器都有一个链接时间优化标志,让您鱼与熊掌兼得。这可能对您的情况有利
- 以增加链接时间为代价
- 只要静态链接的对象包含相关定义(即:不包含动态链接等)
关于c++ - 为什么单独编译并链接时,函数的性能会有所不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21243293/