多线程池化分配器

时间:2011-01-07 00:51:21

标签: c++ multithreading memory-management

我在多线程应用程序中为std :: list对象使用池化内存分配器时遇到了一些问题。

我关注的代码部分独立运行每个线程函数(即线程之间没有通信或同步),因此我想为每个线程设置单独的内存池,其中每个池都不是线程安全(因而快)。

我尝试过使用共享线程安全的单例内存池,发现性能很差,正如预期的那样。

这是我正在努力做的事情的一个非常简化的版本。很多都被包含在伪代码中,抱歉,如果它令人困惑。

/* The thread functor - one instance of MAKE_QUADTREE created for each thread
 */
class make_quadtree
{
private:

/* A non-thread-safe memory pool for int linked list items, let's say that it's 
 * something along the lines of BOOST::OBJECT_POOL
 */
    pooled_allocator<int> item_pool;

/* The problem! - a local class that would be constructed within each std::list as the
 * allocator but really just delegates to ITEM_POOL
 */
    class local_alloc
    {
    public :
    //!! I understand that I can't access ITEM_POOL from within a nested class like
    //!! this, that's really my question - can I get something along these lines to
    //!! work??
        pointer allocate (size_t n) { return ( item_pool.allocate(n) ); }
};

public :
    make_quadtree (): item_pool()    // only construct 1 instance of ITEM_POOL per
                                     // MAKE_QUADTREE object
    {
    /* The kind of data structures - vectors of linked lists
     * The idea is that all of the linked lists should share a local pooled allocator
     */
        std::vector<std::list<int, local_alloc>> lists;

    /* The actual operations - too complicated to show, but in general:
     *
     * - The vector LISTS is grown as a quadtree is built, it's size is the number of
     *   quadtree "boxes"
     *
     * - Each element of LISTS (each linked list) represents the ID's of items
     *   contained within each quadtree box (say they're xy points), as the quadtree
     *   is grown a lot of ID pop/push-ing between lists occurs, hence the memory pool
     *   is important for performance
*/
    }
};

所以我的问题是我希望每个线程的functor实例都有一个内存池实例,但是在每个线程中,functor在多个std :: list对象之间共享池。

2 个答案:

答案 0 :(得分:0)

为什么不构造一个local_alloc实例,并引用make_quadtree?

答案 1 :(得分:0)

特定于线程的分配器是一个挑战。

我花了一些时间寻找一个“现成的”特定于线程的分配器。我找到的最好的是囤积(hoard.org)。这提供了显着的性能改进,但是囤积有一些严重的缺点

  • 我在测试期间遇到了一些崩溃
  • 商业许可是 昂贵
  • 它'挂钩'系统调用 malloc,一种我认为狡猾的技术。

所以我决定基于boost :: pool和boost :: threadspecificptr来推送我自己的特定于线程的内存分配器。这需要少量的恕我直言,非常先进的C ++代码,但现在似乎运作良好。

现在已经有几个月了,我看了一下这个细节,但也许我可以再看看它。

您的评论是您正在寻找特定于线程但不是线程安全的分配器。这是有道理的,因为如果分配器是特定于线程的,则它不需要是线程安全的。但是,根据我的经验,只要不发生争用,线程安全的额外负担是微不足道的。

然而,所有这些理论都很有趣,但我认为我们应该继续实践。我相信我们需要一个小型的仪表化独立程序来演示您需要解决的问题。我有一个与std :: multiset分配非常相似的问题并编写了你可以在这里看到的程序:Parallel reads from STL containers

如果您可以编写类似的东西,显示您的问题,那么我可以检查我的线程特定内存分配器是否可以在您的情况下有利地应用。