Как статически ссылаться на TBB?
Как я могу статически связать библиотеки Intel TBB с моим приложением?
Я знаю все предостережения, такие как несправедливое распределение нагрузки планировщика, но мне не нужен планировщик, просто контейнеры, так что все в порядке.
В любом случае, я знаю, что это можно сделать, хотя его недокументированный, однако я просто не могу найти способ сделать это прямо сейчас (хотя я видел его где-то раньше).
Знает ли кто-нибудь или имеет какие-либо подсказки?
спасибо
Ответы
Ответ 1
Это настоятельно не рекомендуется:
Есть ли версия TBB, которая предоставляет статически связанные библиотеки?
TBB не предоставляется как статически связанная библиотека по следующим причинам *:
Большинство библиотек работают локально. Например, Intel (R) MKL FFT преобразует массив. Не имеет значения, сколько копий БПФ есть. Несколько копий и версий могут сосуществовать без труда. Но некоторые библиотеки управляют ресурсами программы, такими как память и процессоры. Например, сборщики мусора контролируют распределение памяти в программе. Аналогично, TBB контролирует планирование задач в рамках программы. Чтобы эффективно выполнять свою работу, каждый из них должен быть одноэлементным; то есть иметь единственный экземпляр, который может координировать действия по всей программе. Разрешение k экземпляров планировщика TBB в одной программе приведет к тому, что в k раз больше программных потоков, чем аппаратные потоки. Программа будет работать неэффективно, потому что машина будет переполнена кодовым коэффициентом k, что приведет к большему перераспределению контекста, кэш-памяти и потреблению памяти. Более того, эффективная поддержка TBB для вложенных parallelism будет отменена, если вложенные parallelism возникли из вложенных вызовов отдельных планировщиков.
Наиболее практичным решением для создания однострочного общесистемного масштаба является динамическая разделяемая библиотека, содержащая singleton. Конечно, если планировщики могут сотрудничать, нам не нужен синглтон. Но для этого сотрудничества требуется централизованный агент для общения; т.е. синглтон!
Наше решение опустить статически связываемую версию TBB сильно повлияло на наш опыт OpenMP. Подобно TBB, OpenMP также пытается планировать программу. Когда-то была предоставлена статическая версия времени выполнения OpenMP, и это был постоянный источник проблем, возникающих из дублирующих планировщиков. Мы считаем, что лучше не повторять эту историю. В качестве косвенного доказательства обоснованности этих соображений мы могли бы указать на то, что Microsoft Visual С++ обеспечивает поддержку OpenMP через динамические библиотеки.
Источник: http://www.threadingbuildingblocks.org/faq/11#sthash.t3BrizFQ.dpuf
Ответ 2
EDIT - Изменено для использования extra_inc
. Спасибо Джеффу!
Создайте со следующим параметром:
make extra_inc=big_iron.inc
Будут построены статические библиотеки. См. Оговорки в build/big_iron.inc
.
Ответ 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
Ответ 4
Создание статических библиотек из источника
После получения исходного кода из https://www.threadingbuildingblocks.org/, создайте TBB следующим образом:
make extra_inc=big_iron.inc
Если вам нужны дополнительные параметры, вместо этого создайте так:
make extra_inc=big_iron.inc <extra options>
Запуск нескольких программ TBB за node
Если вы запускаете многопроцессорное приложение, например. используя 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 либо не поддерживали разделяемые библиотеки, либо плохо работали при их использовании из-за отсутствия локально смонтированной файловой системы.
Ответ 5
К сожалению, это не представляется возможным: С сайта TBB..
Одно из предложений на форуме Intel заключалось в том, чтобы скомпилировать его вручную, если вам действительно нужна статическая связь: От Intel Forum.
Ответ 6
Несмотря на то, что команда TBB официально не одобрена, вы можете создать свою собственную статически связанную версию TBB с помощью make extra_inc=big_iron.inc
.
Я не тестировал его в 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:
- Вызов g++ с помощью переключателя
-static
- Ссылка на tbb (
-ltbb
) и pthread (-lpthread
)
В моем тесте мне также нужно было явно ссылаться на все .o
файлы из версии TBB вручную. В зависимости от вашего проекта вам также может потребоваться передать -pthread
в gcc.
Я создал игрушечный пример для документирования всех шагов в этом репозитории Github:
Он также содержит тестовый код, чтобы убедиться, что сгенерированный двоичный файл переносится в других дистрибутивах Linux.
Ответ 7
Просто соедините файлы, я просто сделал это и работаю. Вот файл 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')