问题:当我单独编译并链接时,为什么函数的性能会有所不同?
首先, CODE
的 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 ++和Microsofts“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和@TomaszKłak的回答,问题已得到解决。我现在用命令编译
cl /O2 /Oi /GL main.cpp randoms.cpp
/ GL标志执行链接时间优化。我可以单独编译文件,但仍然可以进行内联。
答案 0 :(得分:1)
如果函数在定义它的同一翻译单元中使用,则可以内联该用法,从而消除函数调用的开销。
答案 1 :(得分:1)
这是因为内联。因为在编译main.cpp
时,编译器会看到函数 definitions ,它可以在调用站点内联它们,而不是为实际函数调用生成代码 - 保存在调用帧上。
答案 2 :(得分:1)
有两件事情浮现在脑海中。
首先,内联可能会受到影响(通过在编译调用站点TU时使主体不可用,编译器无法内联代码)。在现代C ++中,内联是一种 巨大的 优化潜力(因为它经常会内联多个级别的调用,并且生成的主体经常会产生更有趣的优化)。
现在很多编译器都有一个 链接时间优化 标志,让你有蛋糕,也吃掉它。这可能会使您的情况受益