我的 C++11 测试表明 sort(vector<string>) 比 C++03 还要慢,有什么错误吗?
My C++11 test show that sort(vector<string>) is even slower than C++03, any error?
有了正确的值引用和移动语义,C++11 的 swap/sort 速度应该等于或大于 C++03。所以我设计了一个简单的实验来测试这个。
我用-O2编译并运行它,用c++03和c++11标准。
$g++ test.cpp -O2 && ./a.out
10240000 end construction
sort 10240000 spent1.40035
$g++ test.cpp -O2 -std=c++11 && ./a.out
10240000 end construction
sort 10240000 spent2.25684
所以看起来启用了 C++11,程序变慢了。
我在一个非常新的 mac 和 gcc 环境中:
$gcc -v
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 7.3.0 (clang-703.0.31)
Target: x86_64-apple-darwin15.6.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
下面是源代码:
#include<string>
#include<algorithm>
#include<vector>
#include<cstdlib>
#include<cstdio>
#include<iostream>
#include<ctime>
using namespace std;
string randomString()
{
const size_t scale=600;
char ret[scale];
for(size_t i=0;i<scale;++i)
{
double rand0to1=(double)rand()/RAND_MAX;
ret[i]=(char)rand0to1*92+33;
}
return ret;
}
int main()
{
srand(time(NULL));
const size_t scale=10240000;
vector<string> vs;
vs.reserve(scale);
for(size_t i=0;i<scale;++i)
{
vs.push_back(randomString());
}
cout<<vs.size()<<" end construction\n";
clock_t begin=clock();
sort(vs.begin(),vs.end());
clock_t end=clock();
double duration=(double)(end-begin)/CLOCKS_PER_SEC;
cout<<"sort "<<scale<<" spent"<<duration<<"\n";
return 0;
}
我的程序或理解有任何错误,如何解释我的测试结果?
真的需要你的专业知识!
您的测试代码有几个问题。
您在 ret
中生成的字符串未以 null 结尾,因此它将包含堆栈中的垃圾,这可能会随着编译器设置而改变。这是导致您出现奇怪结果的最可能原因:c++11 版本对较长的字符串进行排序。
您的转换导致字符串完全相同。这不是测量的实际问题,但可能不是您对测试感兴趣的问题。
您不应使用真正随机的种子进行基准测试。您希望在每个 运行 获得可再现性时生成相同的字符串。
此固定版本代码:
#include<string>
#include<algorithm>
#include<vector>
#include<cstdlib>
#include<cstdio>
#include<iostream>
#include<ctime>
using namespace std;
string randomString()
{
const size_t scale=600;
char ret[scale];
for(size_t i=0;i<scale;++i)
{
double rand0to1=(double)rand()/RAND_MAX;
ret[i]=(char)(rand0to1*92+33);
}
ret[scale-1] = 0;
return ret;
}
int main()
{
srand(1);
const size_t scale=10240000;
vector<string> vs;
vs.reserve(scale);
for(size_t i=0;i<scale;++i)
{
vs.push_back(randomString());
}
cout<<vs.size()<<" end construction\n";
clock_t begin=clock();
sort(vs.begin(),vs.end());
clock_t end=clock();
double duration=(double)(end-begin)/CLOCKS_PER_SEC;
cout<<"sort "<<scale<<" spent "<<duration<<"\n";
return 0;
}
产生了我相信你所期待的:
$ g++ -O2 -std=c++03 test.cpp && ./a.out
10240000 end construction
sort 10240000 spent 10.8765
$ g++ -O2 -std=c++11 test.cpp && ./a.out
10240000 end construction
sort 10240000 spent 8.72834
顺便说一句,mac 上 Xcode 的 g++ 实际上是 clang。但结果是相似的:
$ clang++ -O2 -std=c++03 test.cpp && ./a.out
10240000 end construction
sort 10240000 spent 10.9408
$ clang++ -O2 -std=c++11 test.cpp && ./a.out
10240000 end construction
sort 10240000 spent 8.33261
已使用 g++ 6.2.1 和 clang 3.9.0 进行测试。 -std=c++03
开关很重要,因为没有它,g++ 会以一种提供快速时间的模式编译。
有了正确的值引用和移动语义,C++11 的 swap/sort 速度应该等于或大于 C++03。所以我设计了一个简单的实验来测试这个。
我用-O2编译并运行它,用c++03和c++11标准。
$g++ test.cpp -O2 && ./a.out
10240000 end construction
sort 10240000 spent1.40035
$g++ test.cpp -O2 -std=c++11 && ./a.out
10240000 end construction
sort 10240000 spent2.25684
所以看起来启用了 C++11,程序变慢了。 我在一个非常新的 mac 和 gcc 环境中:
$gcc -v
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 7.3.0 (clang-703.0.31)
Target: x86_64-apple-darwin15.6.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
下面是源代码:
#include<string>
#include<algorithm>
#include<vector>
#include<cstdlib>
#include<cstdio>
#include<iostream>
#include<ctime>
using namespace std;
string randomString()
{
const size_t scale=600;
char ret[scale];
for(size_t i=0;i<scale;++i)
{
double rand0to1=(double)rand()/RAND_MAX;
ret[i]=(char)rand0to1*92+33;
}
return ret;
}
int main()
{
srand(time(NULL));
const size_t scale=10240000;
vector<string> vs;
vs.reserve(scale);
for(size_t i=0;i<scale;++i)
{
vs.push_back(randomString());
}
cout<<vs.size()<<" end construction\n";
clock_t begin=clock();
sort(vs.begin(),vs.end());
clock_t end=clock();
double duration=(double)(end-begin)/CLOCKS_PER_SEC;
cout<<"sort "<<scale<<" spent"<<duration<<"\n";
return 0;
}
我的程序或理解有任何错误,如何解释我的测试结果?
真的需要你的专业知识!
您的测试代码有几个问题。
您在
ret
中生成的字符串未以 null 结尾,因此它将包含堆栈中的垃圾,这可能会随着编译器设置而改变。这是导致您出现奇怪结果的最可能原因:c++11 版本对较长的字符串进行排序。您的转换导致字符串完全相同。这不是测量的实际问题,但可能不是您对测试感兴趣的问题。
您不应使用真正随机的种子进行基准测试。您希望在每个 运行 获得可再现性时生成相同的字符串。
此固定版本代码:
#include<string>
#include<algorithm>
#include<vector>
#include<cstdlib>
#include<cstdio>
#include<iostream>
#include<ctime>
using namespace std;
string randomString()
{
const size_t scale=600;
char ret[scale];
for(size_t i=0;i<scale;++i)
{
double rand0to1=(double)rand()/RAND_MAX;
ret[i]=(char)(rand0to1*92+33);
}
ret[scale-1] = 0;
return ret;
}
int main()
{
srand(1);
const size_t scale=10240000;
vector<string> vs;
vs.reserve(scale);
for(size_t i=0;i<scale;++i)
{
vs.push_back(randomString());
}
cout<<vs.size()<<" end construction\n";
clock_t begin=clock();
sort(vs.begin(),vs.end());
clock_t end=clock();
double duration=(double)(end-begin)/CLOCKS_PER_SEC;
cout<<"sort "<<scale<<" spent "<<duration<<"\n";
return 0;
}
产生了我相信你所期待的:
$ g++ -O2 -std=c++03 test.cpp && ./a.out
10240000 end construction
sort 10240000 spent 10.8765
$ g++ -O2 -std=c++11 test.cpp && ./a.out
10240000 end construction
sort 10240000 spent 8.72834
顺便说一句,mac 上 Xcode 的 g++ 实际上是 clang。但结果是相似的:
$ clang++ -O2 -std=c++03 test.cpp && ./a.out
10240000 end construction
sort 10240000 spent 10.9408
$ clang++ -O2 -std=c++11 test.cpp && ./a.out
10240000 end construction
sort 10240000 spent 8.33261
已使用 g++ 6.2.1 和 clang 3.9.0 进行测试。 -std=c++03
开关很重要,因为没有它,g++ 会以一种提供快速时间的模式编译。