【问题标题】:Boost allocators performance提升分配器性能
【发布时间】:2021-01-05 14:06:55
【问题描述】:

我正在尝试通过使用 boost::container::allocators 来提高性能。

创建a simple experiment:

#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::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::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, std::less<int>, boost::container::adaptive_pool<int>>>();
    setInsertTest<boost::container::set<int>>();
    setInsertTest<boost::container::set<int, std::less<int>, boost::container::node_allocator<int>>>();
    setInsertTest<boost::container::set<int, std::less<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

据我所知,分配器并没有带来任何性能提升。
任何人都可以看看并告诉我我做错了什么吗?

【问题讨论】:

标签: c++ boost c++14 allocator


【解决方案1】:

据我所知,分配器并没有带来任何性能提升。

在您的特定基准测试中,无论您使用什么分配器,在执行 vector&lt;&gt;::push_back 之前调用 vector&lt;&gt;::reserve 都会产生最大的性能提升。

当您不调用vector&lt;&gt;::reserve 时,基准会在向量增长时分配更大的内存块,而这种情况并不是分配器优化的对象。现代分配器通常针对在不同线程中使用时的最小锁争用进行了优化,内存碎片更少,缓存利用率更高,您的基准测试无法从/观察和测量中受益。


setInsertTest 中插入std::rand 调用的结果。这个伪随机数生成器必须通过调用 std::srand(0) 重置,以便每个基准测试使用完全相同的伪随机数序列,否则它会测量来自同一分布的不相交样本的不同容器的性能。


您可能喜欢使用Google Benchmark,因为它会自动进行

  • 时机,
  • 报告,
  • 禁用基准代码省略,
  • 可以报告集中趋势(平均值和中位数)和离散度(标准差)的统计量度

无需为此编写一行代码。

【讨论】:

  • 感谢您的回答! UPD:我通过删除向量测试来更新示例。您已经提到现代分配器减少了内存碎片并更好地使用缓存。我创建了迭代测试来测量集合上的迭代时间。由于更多的缓存命中,我预计分配器的性能会更好。但总体结果是一样的。分配器在此示例中没有性能提升。 PS:GoogleBenchmark 是个好东西,但我现在不需要准确性,我只是在调查整体情况。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-04
  • 2017-10-08
  • 2015-12-26
  • 2013-05-12
相关资源
最近更新 更多