问题描述
我试图通过使用 boost::container::allocators 来提高性能。
#include <chrono>
#include <set>
#include <vector>
#include <iostream>
#include <boost/container/pmr/vector.hpp>
#include <boost/container/pmr/set.hpp>
#include <boost/container/allocator.hpp>
#include <boost/container/node_allocator.hpp>
#include <boost/container/adaptive_pool.hpp>
template<typename Vector>
void pushBackTest(bool makeReserve)
{
Vector v;
const std::size_t count = 10000000;
if (makeReserve)
{
v.reserve(count);
}
auto start = std::chrono::high_resolution_clock::Now();
for (std::size_t i = 0 ; i < count ; ++i)
{
v.push_back(typename Vector::value_type{});
}
auto end = std::chrono::high_resolution_clock::Now();
const std::chrono::duration<double> duration = end - start;
std::cout << duration.count() << std::endl;
}
template<typename Set>
void setInserttest()
{
Set v;
const std::size_t count = 1000000;
auto start = std::chrono::high_resolution_clock::Now();
for (std::size_t i = 0 ; i < count ; ++i)
{
v.insert(std::rand());
}
auto end = std::chrono::high_resolution_clock::Now();
const std::chrono::duration<double> duration = end - start;
std::cout << duration.count() << std::endl;
}
int main()
{
std::srand((unsigned)std::time(nullptr));
std::cout << "Vector" << std::endl;
std::cout << "No reserve" << std::endl;
pushBackTest<std::vector<int>>(false);
pushBackTest<std::vector<int,boost::container::allocator<int>>>(false);
pushBackTest<boost::container::vector<int,boost::container::allocator<int>>>(false);
pushBackTest<boost::container::pmr::vector<int>>(false);
std::cout << "Reserve" << std::endl;
pushBackTest<std::vector<int>>(true);
pushBackTest<std::vector<int,boost::container::allocator<int>>>(true);
pushBackTest<boost::container::vector<int,boost::container::allocator<int>>>(true);
pushBackTest<boost::container::pmr::vector<int>>(true);
std::cout << "Set" << std::endl;
setInsertTest<std::set<int>>();
setInsertTest<std::set<int,std::less<int>,boost::container::node_allocator<int>>>();
setInsertTest<std::set<int,boost::container::adaptive_pool<int>>>();
setInsertTest<boost::container::set<int>>();
setInsertTest<boost::container::set<int,boost::container::node_allocator<int>>>();
setInsertTest<boost::container::set<int,boost::container::adaptive_pool<int>>>();
setInsertTest<boost::container::pmr::set<int>>();
return 0;
}
使用 clang++12 prog.cc -Wall -Wextra -O2 -march=native -I/Opt/wandBox/boost-1.73.0/clang-head/include -std=c++14
编译
结果:
Vector
No reserve
0.10387
0.095851
0.104992
0.0982694
0.102469
Reserve
0.0372922
0.0489831
0.0518053
0.052593
0.0680981
Set
0.760118
0.7739
0.769929
1.09121
0.685224
0.747359
1.18725
据我所知,分配器并没有带来任何性能提升。
任何人都可以看看并告诉我我做错了什么吗?
解决方法
据我所知,分配器没有带来任何性能提升。
在您的特定基准测试中,无论您使用什么分配器,在执行 vector<>::reserve
之前调用 vector<>::push_back
都会产生最大的性能提升。
当您不调用 vector<>::reserve
时,基准测试会在向量增长时分配更大的内存块,而这种情况并不是分配器针对的优化。现代分配器通常针对不同线程使用时的最小锁争用、更少的内存碎片、更好的缓存利用率进行了优化,您的基准测试无法从/观察和衡量这些方面受益。
在 setInsertTest
中插入 std::rand
调用的结果。这个伪随机数生成器必须通过调用 std::srand(0)
重置,以便每个基准使用完全相同的伪随机数序列,否则它会测量不同容器在来自同一分布的不相交样本上的性能。>
您可能喜欢使用 Google Benchmark,因为它可以自动化
- 时间,
- 报告,
- 禁用基准代码省略,
- 可以报告集中趋势(均值和中位数)和离散度(标准差)的统计量度
无需为此编写一行代码。