19

如何将英特尔的 TBB 库静态链接到我的应用程序?我知道调度程序的负载分配不公平等所有注意事项,但我不需要调度程序,只需要容器,所以没关系。

无论如何,我知道这是可以做到的,尽管它没有记录,但是我现在似乎找不到这样做的方法(尽管我以前在某个地方见过它)。

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

谢谢

4

7 回答 7

12

强烈不建议这样做:

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

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

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

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

我们决定省略 TBB 的静态链接版本的决定很大程度上受到了我们的 OpenMP 经验的影响。与 TBB 一样,OpenMP 也尝试跨程序进行调度。曾经提供过静态版本的 OpenMP 运行时,它一直是重复调度程序引起的问题的源头。我们认为最好不要重蹈覆辙。作为这些考虑的有效性的间接证明,我们可以指出 Microsoft Visual C++ 仅通过动态库提供 OpenMP 支持这一事实。

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

于 2013-10-30T13:55:12.423 回答
8

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

使用以下参数构建:

make extra_inc=big_iron.inc

将构建静态库。请参阅 中的注意事项build/big_iron.inc

于 2016-08-09T18:56:19.537 回答
5

从源代码构建静态库

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/madness/madness/blob/master/src/madness/world/thread.cc中找到大型应用程序中的一个示例。

评论文档

此功能已可用多年(至少从 2013 年开始),尽管由于其他答案中描述的原因未记录在案。

历史记录

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

于 2016-10-23T04:05:54.057 回答
3

使用开源版本:

运行“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 构建

于 2014-03-03T09:34:24.090 回答
3

虽然没有得到 TBB 团队的正式认可,但可以使用make extra_inc=big_iron.inc.

我没有在 Windows 或 MacOS 上测试过它,但在 Linux 上,它可以工作(来源):

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)

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

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

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

于 2017-06-04T23:52:33.333 回答
1

不幸的是,这似乎不可能:来自 TBB 网站。.
英特尔论坛上的一项建议是,如果您确实需要静态链接,请手动编译:来自英特尔论坛

于 2009-10-29T12:55:53.320 回答
-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')
于 2012-02-01T15:52:35.733 回答