Intel Threading Building Blocks 编程指南 : 内存分配

转载 2015年11月18日 18:37:59

(原文出自 tbb tutorial ,也许稍有改动。)

Intel Threading Building Blocks(Intel TBB)提供了两种与STL模板类(std::allocator)类似的内存分配器模板。这两类模板(scalable_allocator<T>、cache_aligned_allocator<T>)解决并行编程中的如下关键问题:

  • 可伸缩性    当在线程中使用原本为串行编程而设计的内存分配器因单个同一时间只允许一个线程分配的共享池而竞争的时候,可伸缩性的问题就会凸显。使用内存分配模板scalable_allocator<T>来避免此类可伸缩性瓶颈。这个模板可以提升急速分配、释放内存程序的性能。
  • 伪共享   当两个线程访问同一缓存行的不同字节时,伪共享的问题就会出现。这是因为,缓存行(cache line)是不同处理器缓存间交换信息的单位。如果一个处理器修改了一个缓存行而另外一个处理器读(或者写)同一个缓存行,那么它必须从一个处理器移动到另外一个处理器,即使两个处理处理的是这行内的不同字节。因为缓存行的移动会耗费数百个时钟周期,伪共享会损害性能。

使用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

自动替换malloc等C/C++动态内存分配函数

在windows、Linux操作系统中,可以自动使用Intel TBB中相应的可伸缩实现替换所有标准动态内存分配函数调用(比如:malloc)。在一些场合,可以提升性能。

Linux C/C++动态内存借口替换

替换通过代理库(release:libtbbmalloc_proxy.so.x、debug:libtbbmalloc_proxy_debug.so.x)提供。替换行为可以通过运行时加载代理库(通过LD_PRELOAD)或者链接(linking)代理库实现。代理库实现了以下动态内存函数:

  • C library:malloc,calloc,realloc,free
  • 标准POSIX函数:posix_memalign
  • 废弃的函数:valloc,memalign,pvalloc,mallopt
  • 全局C++操作符:new、delete

动态加载时,要保证代理库以及相应的可伸缩内存分配器库可被访问。要做到这点,可通过在LD_LIBRARY_PATH中包含或者将其加入到/etc/ld.so.conf中(关于Linux下动态库的搜索路径,可参考

替换存在以下限制:

  • 无法应用于使用非标准调用glibc的内存分配器的程序
  • 不支持Mono(一种跨平台的.net环境实现)

例:

下面是一个如何设置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


windows下C++动态内存接口替换

替换通过代理库(release:tbbmalloc_proxy.dll,debug:tbbmalloc_debug_proxy.dll)提供。能以下面的任一种方式实现:

  • 包含头文件 #include "tbb/tbbmalloc_proxy.h"
  • 设置链接参数 

         对于32位代码:tbbmalloc_proxy.lib /INCLUDE:"___TBB_malloc_proxy"  (三个下划线)

         对于64位代码:tbbmalloc_proxy.lib /INCLUDE:"__TBB_malloc_proxy"      (两个下划线)

代理库实现了下面的动态内存函数:

  • 标准C运行时动态内存函数:malloc,calloc,realloc,free
  • 全局C++操作符:new,delete
  • Microsoft C运行时库函数:_msize

同样要保证代理库、可伸缩内存分配库在程序启动时能被加载,例如,可将其路径包含在%PATH%环境变量中。

相关文章推荐

Intel Threading Building Blocks 编程指南:简单循环的并行化

可伸缩并行化的最简单的形式就是能够互不干涉地同时运行的迭代的循环。本节将会说明如何将简单的循环并行化。 定义 Intel Threading Building Blocks(Intel TBB) 组件...

TBB(intel threading building blocks)内存分配算法(一)

开篇:最近研究了一下TBB的内存分配算法,发现设计的非常优雅,故和大家分析一下它的算法思想。 既然是开篇,那么我们就先从最基本的入手来看一下TBB基于Cache对齐的内存管理算法。首先来明确几个概念...
  • realxie
  • realxie
  • 2012年02月11日 15:14
  • 4619

Threading building blocks 编程指南

  • 2014年07月13日 09:17
  • 2.6MB
  • 下载

Intel.Threading.Building.Blocks

  • 2013年12月13日 12:25
  • 2.88MB
  • 下载

TBB(Intel Threading Building Blocks)学习笔记

TBB(Intel Threading Building Blocks)学习笔记 并行与并发是相对的,OS里讲的是并发而在架构方面更多的是说并行。并行是分多个层面的,个人认为基本上可以分为这么几个层...
  • zhu2695
  • zhu2695
  • 2016年04月26日 00:30
  • 403

Intel Threading Building Blocks :基本算法参考及使用

Intel TBB提供的大多数并行算法支持泛型。但是这些受支持的类型必须实现必要的概念方法。并行算法可以嵌套, 例如,一个parallel_for的内部可以调用另一个parallel_for。...

Intel Threading Building Blocks 之 并行循环(一)

Intel Threading Building Blocks(下文简称TBB)是一个C++的并行编程模板库,它能使你的程序充分利用多核CPU的性能优势。从www.threadingbuildingb...

C/C++内存分配方式总结——来自《高质量编程指南》

C/C++内存分配方式有3种:         (1)从静态存储区域分配。内存在程序编译的时候就已经分配好了(即已经编址),这些内存在程序的整个运行都存在。例如全局变量,static变量等。   ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Intel Threading Building Blocks 编程指南 : 内存分配
举报原因:
原因补充:

(最多只允许输入30个字)