malloc /新锁和多线程

时间:2011-11-03 08:44:05

标签: c++ multithreading openmp

如何在多线程环境中使用new

准确地说:我有一段用40个线程运行的代码。每个线程调用new几次。我注意到性能下降,可能是因为线程锁定在new(在__lll_lock_wait_parallel__lll_unlock_wait_parallel中花费了大量时间)。我可以使用new / delete的最佳替代方案是什么?

相关:

6 个答案:

答案 0 :(得分:5)

我不知道“最好的”,但我会尝试一些事情:

  • 降低分配/释放的频率(可能很难)。如果能提高性能,就浪费内存(但不要泄漏)

  • 滚动我自己的每线程分配器并始终使用mmap为同一个线程分配/释放实际内存

滚动你自己的原始分配器:

  • 使用mmap从操作系统中获取大量内存
  • 使用数据结构(链表,树等)来跟踪空闲和已用块
  • 永远不要释放另一个线程分配的数据

我不认为这样做是微不足道的,但如果做得好,它可以提高性能。最毛茸茸的部分是到目前为止跟踪分配,防止碎片等。

本书末尾附近的“ The C Programming Language ”中提供了一个简单的实现(但它使用了brk IIRC)。

答案 1 :(得分:5)

即使您使用new运算符,它也会使用下面的malloc进行分配和释放。重点应放在分配器上,而不是在这些情况下用于达到它的API。

TCMalloc 是专为在多线程环境中获得良好性能而在Google创建的malloc。它是google-perf-tools的一部分。

您可能会看到的另一个malloc是 Hoard 。它与TCMalloc的目标大致相同。

答案 2 :(得分:2)

我认为你应该使用内存池。在项目启动时第一次分配所需的所有内存(如果大小为Fix),并让数组从您分配的第一个数组中获取所需的内存。

答案 3 :(得分:1)

我倾向于在服务器和其他此类应用程序中使用对象池,这些应用程序的特点是持续且频繁地分配和释放大量的几组对象(在服务器中 - 套接字,缓冲区和缓冲区集合类)。这些池是队列,在启动时创建并推送适当数量的实例(例如,我的服务器 - 24000个套接字,48000个集合以及7个不同大小/数量的缓冲池池阵列)。从队列中弹出对象实例并将其重新启动比新/删除要快得多,即使池队列具有锁定,因为它在线程之间共享,(锁定范围越小,争用的可能性越小) 。我的池对象类(从中继承了所有套接字等),有一个私有的'myPool'成员,(在启动时加载)和一个没有参数的'release()'方法&所以任何缓冲区都可以轻松,正确地返回到自己的池中。有问题:

1)Ctor和dtor不会被分配/释放&所以分配的对象包含他们上次使用时留下的所有gunge。这有时可能是有用的(例如,可重用的套接字对象),但通常意味着需要注意,例如,布尔值的初始状态,int的值等等。

2)每个线程的池具有最大的性能改进潜力 - 不需要锁定,但是在每个线程上的加载是间歇性的系统中,这可能是对象浪费。我似乎永远无法逃避这一点,主要是因为我使用池化对象进行线程间通信,因此无论如何release()都必须是线程安全的。

3)消除共享池上的“错误共享”可能很尴尬 - 每个实例应该最初“新建”,以便专门使用整数个缓存页面。至少这只需要在启动时完成一次。

4)如果系统要在池耗尽时恢复弹性,则需要分配更多对象以在需要时添加到池中(池大小随后逐渐增加),或者生产者 - 消费者队列可以使用以便线程在池上阻塞直到释放对象,(由于condvar / semaphore /等待线程阻塞的PC队列速度较慢,在释放之前分配的线程也会在空池上死锁)。

5)需要在开发期间监视池级别,以便可以检测到对象泄漏和双重释放。可以将代码/数据添加到对象/池中以检测发生的错误,但这会影响性能。

答案 4 :(得分:1)

1,你真的要“新”那件事吗?为什么不使用局部变量或每线程堆对象。

2,如果您的开发环境支持它,请查看http://en.wikipedia.org/wiki/Thread-local_storage ...

答案 5 :(得分:0)

由于没有人提及它,我可能还建议尝试使用Boehm's conservative garbage collector;这意味着使用new(gc)代替newGC_malloc代替malloc而不用担心free - 或delete内存对象。几年前,我测量GC_mallocmalloc,它有点慢(GC_malloc可能为25μs而系统malloc则为22μs。)

我不知道Boehm的GC在多线程使用中的性能(但我知道它可以在多线程应用程序中使用)。

Boehm的GC的优势在于您不应该关心free您的数据。