gpt4 book ai didi

c++ - 没有内存重新分配的 std::set 的替代方案?

转载 作者:IT老高 更新时间:2023-10-28 22:25:25 26 4
gpt4 key购买 nike

在一个应用程序中,我详尽地生成了许多子问题,并使用“std::set”操作来解决它们。为此,我需要在排序列表上“insert”和“find”元素以及“迭代”。

问题在于,对于数百万个子问题中的每一个,每次我在集合中插入一个元素时,“std::set”实现都会分配新的内存,这使得整个应用程序非常慢:

{   // allocate a non-value node
_Nodeptr _Pnode = this->_Getal().allocate(1); // <- bottleneck of the program

是否有一些 STL 结构允许我在“O(log(n))”中进行上述操作而不重新分配任何内存?

最佳答案

使用自定义分配器似乎可以减少构建和发布 std::set<...> 所花费的时间。 .下面是一个简单分配器的完整演示以及一个分析结果时间的程序。

#include <algorithm>
#include <chrono>
#include <cstdlib>
#include <iostream>
#include <iterator>
#include <memory>
#include <set>
#include <vector>

// ----------------------------------------------------------------------------

template <typename T, std::size_t pool_size = 1024>
class pool_allocator
{
private:
std::vector<T*> d_pools;
T* d_next;
T* d_end;
public:
template <typename O>
struct rebind {
typedef pool_allocator<O, pool_size> other;
};
pool_allocator(): d_next(), d_end() {}
~pool_allocator() {
std::for_each(this->d_pools.rbegin(), this->d_pools.rend(),
[](T* memory){ operator delete(memory); });
}
typedef T value_type;
T* allocate(std::size_t n) {
if (std::size_t(this->d_end - this->d_next) < n) {
if (pool_size < n) {
// custom allocation for bigger number of objects
this->d_pools.push_back(static_cast<T*>(operator new(sizeof(T) * n)));
return this->d_pools.back();
}
this->d_pools.push_back(static_cast<T*>(operator new(sizeof(T) * pool_size)));
this->d_next = this->d_pools.back();
this->d_end = this->d_next + pool_size;
}
T* rc(this->d_next);
this->d_next += n;
return rc;
}
void deallocate(T*, std::size_t) {
// this could try to recycle buffers
}
};

// ----------------------------------------------------------------------------

template <typename Allocator>
void time(char const* name, std::vector<int> const& random) {
std::cout << "running " << name << std::flush;
using namespace std::chrono;
high_resolution_clock::time_point start(high_resolution_clock::now());

std::size_t size(0);
{
std::set<int, std::less<int>, Allocator> values;
for (int value: random) {
values.insert(value);
}
size = values.size();
}

high_resolution_clock::time_point end(high_resolution_clock::now());
std::cout << ": size=" << size << " time="
<< duration_cast<milliseconds>(end - start).count() << "ms\n";
}

// ----------------------------------------------------------------------------

int main()
{
std::cout << "preparing..." << std::flush;
std::size_t count(10000000);
std::vector<int> random;
random.reserve(count);
std::generate_n(std::back_inserter(random), count, [](){ return std::rand(); });
std::cout << "done\n";

time<std::allocator<int>>("default allocator ", random);
time<pool_allocator<int, 32>>("custom allocator (32) ", random);
time<pool_allocator<int, 256>>("custom allocator (256) ", random);
time<pool_allocator<int, 1024>>("custom allocator (1024)", random);
time<pool_allocator<int, 2048>>("custom allocator (2048)", random);
time<pool_allocator<int, 4096>>("custom allocator (4096)", random);
time<std::allocator<int>>("default allocator ", random);
}

// results from clang/libc++:
// preparing...done
// running default allocator : size=10000000 time=13927ms
// running custom allocator (32) : size=10000000 time=9260ms
// running custom allocator (256) : size=10000000 time=9511ms
// running custom allocator (1024): size=10000000 time=9172ms
// running custom allocator (2048): size=10000000 time=9153ms
// running custom allocator (4096): size=10000000 time=9599ms
// running default allocator : size=10000000 time=13730ms

// results from gcc/libstdc++:
// preparing...done
// running default allocator : size=10000000 time=15814ms
// running custom allocator (32) : size=10000000 time=10868ms
// running custom allocator (256) : size=10000000 time=10229ms
// running custom allocator (1024): size=10000000 time=10556ms
// running custom allocator (2048): size=10000000 time=10392ms
// running custom allocator (4096): size=10000000 time=10664ms
// running default allocator : size=10000000 time=17941ms

关于c++ - 没有内存重新分配的 std::set 的替代方案?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24096466/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com