1. 程式人生 > >初識英特爾執行緒構建模組之記憶體管理tbb_malloc

初識英特爾執行緒構建模組之記憶體管理tbb_malloc

什麼是TBB?

TBB(Thread Building Blocks)是英特爾釋出的一個庫,全稱為 Threading Building Blocks,裡面包含了 Algorithms、Containers、Memory Allocation、Synchronization、Timing、Task Scheduling這六個模組。暫時我只用到了Memory Allocation模組,其他的沒有用到。

摘自百度百科:TBB,Thread Building Blocks,執行緒構建模組,是Intel公司開發的並行程式設計開發的工具。OSCON 上,Intel 宣佈,Threading Building Blocks,Intel 眾多軟體開發工具中的一個,open source 了。協議是 GPLv2。TBB 獲得過 17 屆 Jolt Productivity Awards,是一套 C++ 模板庫,和直接利用 OS API 寫程式的 raw thread 比,在並行程式設計方面提供了適當的抽象,當然還包括更多其他內容,比如 task 概念,常用演算法的成熟實現,自動負載均衡特 性還有不繫結 CPU 數量的靈活的可擴充套件性等等。STL 之父,Alexander Stepanov 對此評價不錯,他說“Threading Building Blocks… could become a basis for the concurrency dimension of the C++ standard library”。其他 TBB 的早期使用者,包括 Autodesk,Sun,Red Hat, Turbo Linux 等亦然。現在 O’Reilly 已經出版了一本 Intel Threading Building Blocks: Outfitting C++ for Multi-core Processor Parallelism。
使用tbb_malloc有什麼好處?

tbb_malloc是完全符合STL Allocator標準,完全可以作為STL中各種容器的記憶體介面卡。純純的C++ style,各位cpper用起來想來應該會很舒服。

如何使用tbb_malloc?

tbb_malloc提供了多種申請記憶體的類以便使用的不同的場合,具體請檢視官方文件。我們主要來看下tbb::cache_aligned_allocator< T >。

#include <tbb/cache_aligned_allocator.h>

namespace my_alloactor
{
struct alloc_maker
{
  template <typename T>
  static tbb::cache_aligned_allocator<T>& get_allocator()
  {
    static tbb::cache_aligned_allocator<T> ret;
    return ret;
  }
};
}

#define MY_ALLOC(T, n) ::my_alloactor::alloc_maker::get_allocator<T>().allocate(n)
#define MY_FREE(T, p, n) ::my_alloactor::alloc_maker::get_allocator<T>().deallocate(p, n)
#define MY_NEW(T) new ((void*)(::my_alloactor::alloc_maker::get_allocator<T>().allocate(1))) T
#define MY_DELETE(T, p) if (p) {::my_alloactor::alloc_maker::get_allocator<T>().destroy(p); ::my_alloactor::alloc_maker::get_allocator<T>().deallocate(p, 1);}

namespace my_alloactor
{
struct deleter
{
  template <typename T>
  void operator()(T* p)
  {
    MY_DELETE(T, p);
  }
};
}

以上封裝的使用方法如下:

my_t* mt = MY_NEW(my_t)(/* construct funtion arg list */)

當然了,你還可以直接用來作為容器的預設記憶體介面卡,例如:

typedef std::vector<int, tbb::cache_aligned_allocator<int> > tbb_malloc_vector;
tbb_malloc_vector my_vec;

還可以將其改造成記憶體池,使用一個位元組的char作為模板引數即可,如下:

tbb::cache_aligned_allocator<char> memory_pool;
void* mem = memory_pool.allocate(100); // 即可申請100位元組的記憶體

使用自定義資料結構:

tbb::cache_aligned_allocator<my_t> alloc;
void* mem = alloc.allocate(1);
my_t* mt = new(m)my_t(/*arg list*/)

申請多個自定義資料結構的記憶體:

tbb::cache_aligned_allocator<my_t> alloc;
my_t* array = (my_t*)alloc.allocate(100);

for (size_t i = 0; i < 100; ++i)
{
  array[i] = new (array[i])my_t(/*arg list*/)
}

不過需要注意的是如果迴圈過程中某個new失敗了,需要釋放之前new的記憶體以及資料。

tbb::cache_aligned_allocator<T>的用法也就這麼多了,其他的幾個allocate類也沒用過,tbb的有一本書叫《Intel Threading Building Blocks: Outfitting C++ for Multi-core Processor Parallelism》,有中文版本,不過裡面的例子也是非常少。

遊戲專案中國外使用tbb的多,mangos中使用了tbb,大家有興趣可以翻翻mangos的程式碼。

很多遊戲啟動的時候會提示找不到tbb_malloc.dll或者tbb.dll,玩家需要自己去tbb官網下載編譯好的dll放進去。

btw.感謝nous對tbb用法的指導。