(原文出自 tbb tutorial ,也许稍有改动。)
Intel Threading Building Blocks(Intel TBB)提供了两种与STL模板类(std::allocator)类似的内存分配器模板。这两类模板(scalable_allocator<T>、cache_aligned_allocator<T>)解决并行编程中的如下关键问题:
使用cache_aligned_allocator<T>类在某个缓存行分配。两个使用cache_aligned_allocator分配的对象能被确保不会使用伪共享。如果一个对象使用cache_aligned_allocator<T>分配,而另外一个对象使用了不同的方式,就没有了这种保证。cache_aligned_allocator<T>的接口类似std::allocator,所以你可以将它作为allocator参数传递给STL的模板类。
下面的代码展示了如何声明一个使用cache_aligned_allocator作为分配器的STL vector:
std::vector<int,cache_aligned_allocator<int> >;
cache_aligned_allocator<T>的设计功能的实现伴随着空间开销,因为它必须至少分配一条缓存行占用的内存,即使是对很小的对象。所以,如果伪共享不成问题,就别使用cache_aligned_allocator<T>。可伸缩内存分配器包含了Intel的PSL CTG团队开发的McRT技术。
scalable_allocator<T>模板需要Intel TBB 可伸缩内存分配器库。它并不需要Intel TBB的常规库,并且能与Intel TBB独立开来使用。如果没有指定可伸缩分配器库,模板tbb_allocator<T>、cache_aligned_allocator<T>就会使用malloc、free等标准库提供的内存分配函数。因此,甚至可以在忽略可伸缩内存分配器库的应用中使用这些模板。Intel Threading Building Blocks的其余部分,有没有Intel TBB可伸缩内存分配器库都可以使用。
模板 |
需求 |
注意事项 |
scalable_allocator<T> |
Intel TBB可伸缩内存分配器库 |
|
tbb_allocator<T>、cache_aligned_allocator<T> |
如果没有指定TBB库,就使用malloc、free |
在windows、Linux操作系统中,可以自动使用Intel TBB中相应的可伸缩实现替换所有标准动态内存分配函数调用(比如:malloc)。在一些场合,可以提升性能。
替换通过代理库(release:libtbbmalloc_proxy.so.x、debug:libtbbmalloc_proxy_debug.so.x)提供。替换行为可以通过运行时加载代理库(通过LD_PRELOAD)或者链接(linking)代理库实现。代理库实现了以下动态内存函数:
动态加载时,要保证代理库以及相应的可伸缩内存分配器库可被访问。要做到这点,可通过在LD_LIBRARY_PATH中包含或者将其加入到/etc/ld.so.conf中(关于Linux下动态库的搜索路径,可参考)
替换存在以下限制:
例:
下面是一个如何设置LD_PRELOAD以及链接程序使用替换的例子。
# Set LD_PRELOAD so that loader loads release version of proxy LD_PRELOAD=libtbbmalloc_proxy.so.2 # Link with release version of proxy and scalable allocator g++ foo.o bar.o -ltbbmalloc_proxy -ltbbmalloc -o a.out
使用Debug版本的库:
# Set LD_PRELOAD so that loader loads debug version of proxy LD_PRELOAD=libtbbmalloc_proxy_debug.so.2 # Link with debug version of proxy and scalable allocator g++ foo.o bar.o -ltbbmalloc_proxy_debug -ltbbmalloc_debug -o a.out
替换通过代理库(release:tbbmalloc_proxy.dll,debug:tbbmalloc_debug_proxy.dll)提供。能以下面的任一种方式实现:
对于32位代码:tbbmalloc_proxy.lib /INCLUDE:"___TBB_malloc_proxy" (三个下划线)
对于64位代码:tbbmalloc_proxy.lib /INCLUDE:"__TBB_malloc_proxy" (两个下划线)
代理库实现了下面的动态内存函数:
同样要保证代理库、可伸缩内存分配库在程序启动时能被加载,例如,可将其路径包含在%PATH%环境变量中。