Question

I've a multithreaded (Cilk) program where each thread use a temporary std::set. There are a lot of allocations on these std::set so that I'm trying to use some pool allocators namely boost::fast_pool_allocator:

using allocator = boost::fast_pool_allocator< SGroup::type >;
using set = std::set<SGroup::type, std::less<SGroup::type>, allocator>;

But now the performances are much worse because of concurrent access to the allocator. One crucial fact is that the sets are never communicated among the threads so that I can use a thread local allocators. However, as shown in the previous code, I'm not constructing allocator objects but passing template parameters to the std::set constructor.

So here is my question: is it possible to construct multiple boost::fast_pool_allocator to use them as thread local pool allocator ?

Edit : I removed stupid std::pair allocations.

Was it helpful?

Solution

EDIT

Mmm. I had an answer here that I pieced together from things I remembered seeing. However, upon further inspection it looks like all the allocators actually work with Singleton Pools that are never thread safe without synchronization. In fact, the null_mutex is likely in a detail namespace for this very reason: it only makes sense to use it if you know the program doesn't use threads (well, outisde the main thread) at all.

Aside from this apparent debacle, you could probably use object_pool directly. But it's not an allocator, so it wouldn't serve you for your container example.


Original Answer Text:

You can pass an allocator instance at construction:

#include <boost/pool/pool.hpp>
#include <boost/pool/pool_alloc.hpp>
#include <boost/thread.hpp>
#include <set>

struct SGroup
{
    int data;
    typedef int type;
};

using allocator = boost::fast_pool_allocator<SGroup::type>;
using set = std::set<SGroup::type, std::less<SGroup::type>, allocator>;

void thread_function()
{
    allocator alloc; // thread local
    set myset(set::key_compare(), alloc);

    // do stuff
}

int main()
{
    boost::thread_group group;
    for (int i = 0; i<10; ++i)
        group.create_thread(thread_function);

    group.join_all();
}

Let me read the docs on how to disable thread-awareness on the allocator :)

Found it in an example:

typedef boost::fast_pool_allocator<SGroup::type,
   boost::default_user_allocator_new_delete,
   boost::details::pool::null_mutex> allocator;

The example in boost/libs/pool/example/time_pool_alloc.hpp should help you get started benchmarking the difference(s) in performance

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top