如何将intel's TBB libraries静态链接到我的应用程序? 我知道all the caveats,例如调度程序的不公平负载分配,但我不需要调度程序,只需要容器,所以没关系。
无论如何我知道这可以做到,虽然它没有记录,但我现在似乎无法找到办法(虽然我已经在某个地方见过它)。
那么有人知道或有任何线索吗?
感谢
答案 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>
如果您运行多处理应用程序,例如使用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
开关-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')