如何静态链接到TBB?

时间:2009-03-12 11:50:27

标签: c++ linker tbb

如何将intel's TBB libraries静态链接到我的应用程序? 我知道all the caveats,例如调度程序的不公平负载分配,但我不需要调度程序,只需要容器,所以没关系。

无论如何我知道这可以做到,虽然它没有记录,但我现在似乎无法找到办法(虽然我已经在某个地方见过它)。

那么有人知道或有任何线索吗?

感谢

7 个答案:

答案 0 :(得分:11)

强烈建议不要这样做:

  

是否有提供静态链接库的TBB版本?

     

TBB不是作为静态链接库提供的,原因如下*:

     

大多数图书馆都在本地运营。例如,英特尔(R)MKL FFT转换阵列。与FFT有多少副本无关。多个副本和版本可以毫无困难地共存。但是一些库控制程序范围的资源,例如内存和处理器。例如,垃圾收集器控制程序中的内存分配。类似地,TBB控制跨程序的任务调度。为了有效地完成工作,每个人都必须是单身人士;也就是说,有一个唯一的实例可以协调整个程序的活动。在单个程序中允许TBB调度程序的k个实例将导致软件线程的数量是硬件线程的k倍。该程序运行效率低,因为机器将被k因子超额认购,导致更多的上下文切换,高速缓存争用和内存消耗。此外,当嵌套并行性来自不同调度程序的嵌套调用时,TBB对嵌套并行性的有效支持将被否定。

     

创建程序范围单例的最实用的解决方案是包含单例的动态共享库。当然,如果调度程序可以合作,我们就不需要单例。但这种合作需要集中的代理人进行沟通;就是单身人士!

     

我们决定省略静态链接版本的TBB受到我们OpenMP经验的强烈影响。与TBB一样,OpenMP也尝试安排整个计划。曾经提供过静态版本的OpenMP运行时,它一直是重复调度程序引起的问题的根源。我们认为最好不要重复那段历史。作为这些考虑的有效性的间接证明,我们可以指出Microsoft Visual C ++仅通过动态库提供OpenMP支持这一事实。

来源:http://www.threadingbuildingblocks.org/faq/11#sthash.t3BrizFQ.dpuf

答案 1 :(得分:8)

编辑 - 已更改为使用extra_inc。谢谢杰夫!

使用以下参数构建:

make extra_inc=big_iron.inc

将构建静态库。请参阅build/big_iron.inc中的警告。

答案 2 :(得分:4)

从源

构建静态库

https://www.threadingbuildingblocks.org/获取源代码后,按照以下方式构建TBB:

make extra_inc=big_iron.inc

如果您需要额外的选项,那么建立如下:

make extra_inc=big_iron.inc <extra options>

每个节点运行多个TBB程序

如果您运行多处理应用程序,例如使用MPI,您可能需要使用适当数量的线程显式初始化TBB调度程序,以避免超额订阅。

大型应用程序中的一个示例可以在https://github.com/m-a-d-n-e-s-s/madness/blob/master/src/madness/world/thread.cc中找到。

评论文件

此功能已推出多年(至少自2013年起),但由于其他答案中描述的原因未对此进行记录。

历史记录

最初开发此功能是因为IBM Blue Gene和Cray超级计算机不支持共享库,或者在使用它们时性能不佳,原因是缺少本地安装的文件系统。

答案 3 :(得分:2)

使用开源版本:

运行“make tbb”后,转到build / linux_xxxxxxxx_release文件夹。

然后运行:

ar -r libtbb.a concurrent_hash_map.o concurrent_queue.o concurrent_vector.o 
dynamic_link.o itt_notify.o cache_aligned_allocator.o pipeline.o queuing_mutex.o 
queuing_rw_mutex.o reader_writer_lock.o spin_rw_mutex.o spin_mutex.o critical_section.o
task.o tbb_misc.o tbb_misc_ex.o mutex.o recursive_mutex.o condition_variable.o 
tbb_thread.o concurrent_monitor.o semaphore.o private_server.o rml_tbb.o 
task_group_context.o governor.o market.o arena.o scheduler.o observer_proxy.o 
tbb_statistics.o tbb_main.o concurrent_vector_v2.o concurrent_queue_v2.o 
spin_rw_mutex_v2.o task_v2.o

你应该把libtbb.a作为输出。

请注意,您的程序应使用“-ldl”和libtbb.a

构建

答案 4 :(得分:2)

虽然TBB团队未正式认可,但可以使用make extra_inc=big_iron.inc构建您自己的TBB静态链接版本。

我没有在Windows或MacOS上测试它,但在Linux上,它有效(source):

wget https://github.com/01org/tbb/archive/2017_U6.tar.gz
tar xzfv 2017_U6.tar.gz
cd tbb-2017_U6
make extra_inc=big_iron.inc

生成的文件位于tbb-2017_U6/build/linux*release

将应用程序链接到静态TBB版本时:

  • 使用-static开关
  • 调用g ++
  • 与tbb(-ltbb)和pthread(-lpthread
  • 的链接

在我的测试中,我还需要明确地引用手动构建TBB版本中的所有.o文件。根据您的项目,您可能还需要将-pthread传递给gcc。

我创建了一个玩具示例来记录此Github存储库中的所有步骤:

它还包含测试代码,以确保生成的二进制文件在其他Linux发行版上是可移植的。

答案 5 :(得分:1)

不幸的是,这似乎不可能:From TBB site. 英特尔论坛的一个建议是,如果您真的需要静态链接,请手动编译它:From Intel Forum

答案 6 :(得分:-1)

只需链接文件,我就这样做并且有效。这是SConscript文件。有两个小问题,一个在tbb和tbbmalloc中具有相同名称的符号,我必须阻止它被多重定义,并且我阻止了ITT_NOTIFY的使用,因为它在两个库中创建了另一个具有相同名称的符号。

Import('g_CONFIGURATION')
import os
import SCutils
import utils

tbb_basedir = os.path.join(
    g_CONFIGURATION['basedir'],
    '3rd-party/tbb40_233oss/')

#print 'TBB base:', tbb_basedir
#print 'CWD: ', os.getcwd()

ccflags = []
cxxflags = [
    '-m64',
    '-march=native',
    '-I{0}'.format(tbb_basedir),
    '-I{0}'.format(os.path.join(tbb_basedir, 'src')),
    #'-I{0}'.format(os.path.join(tbb_basedir, 'src/tbb')),
    '-I{0}'.format(os.path.join(tbb_basedir, 'src/rml/include')),
    '-I{0}'.format(os.path.join(tbb_basedir, 'include')),
]
cppdefines = [
#    'DO_ITT_NOTIFY',
    'USE_PTHREAD',
    '__TBB_BUILD=1',
]
linkflags = []

if g_CONFIGURATION['build'] == 'debug':
    ccflags.extend([
        '-O0',
        '-g',
        '-ggdb2',
    ])
    cppdefines.extend([
        'TBB_USE_DEBUG',
    ])

else:
    ccflags.extend([
        '-O2',
    ])


tbbenv = Environment(
    platform = 'posix',
    CCFLAGS=ccflags,
    CXXFLAGS=cxxflags,
    CPPDEFINES=cppdefines,
    LINKFLAGS=linkflags
)

############################################################################
# Build verbosity
if not SCutils.has_option('verbose'):
    SCutils.setup_quiet_build(tbbenv, True if SCutils.has_option('colorblind') else False)
############################################################################



tbbmallocenv = tbbenv.Clone()

tbbmallocenv.Append(CCFLAGS=[
    '-fno-rtti',
    '-fno-exceptions',
    '-fno-schedule-insns2',
])

#tbbenv.Command('version_string.tmp', None, '')

# Write version_string.tmp
with open(os.path.join(os.getcwd(), 'version_string.tmp'), 'wb') as fd:
    (out, err, ret) = utils.xcall([
        '/bin/bash',
        os.path.join(g_CONFIGURATION['basedir'], '3rd-party/tbb40_233oss/build/version_info_linux.sh')
    ])

    if ret:
        raise SCons.Errors.StopError('version_info_linux.sh execution failed')

    fd.write(out);
    #print 'put version_string in', os.path.join(os.getcwd(), 'version_string.tmp')
    #print out
    fd.close()

result = []

def setup_tbb():
    print 'CWD: ', os.getcwd()
    tbb_sources = SCutils.find_files(os.path.join(tbb_basedir,'src/tbb'), r'^.*\.cpp$')
    tbb_sources.extend([
        'src/tbbmalloc/frontend.cpp',
        'src/tbbmalloc/backref.cpp',
        'src/tbbmalloc/tbbmalloc.cpp',
        'src/tbbmalloc/large_objects.cpp',
        'src/tbbmalloc/backend.cpp',
        'src/rml/client/rml_tbb.cpp',
    ])


    print tbb_sources
    result.append(tbbenv.StaticLibrary(target='libtbb', source=tbb_sources))


setup_tbb()

Return('result')