Как статически привязать к TBB?

Как я могу статически связать библиотеки Intel TBB с моим приложением? Я знаю все предостережения, такие как несправедливое распределение нагрузки планировщика, но Планировщик мне не нужен, только контейнеры, так что все в порядке.

В любом случае я знаю, что это можно сделать, хотя это недокументировано, однако я просто не могу найти способ сделать это прямо сейчас (хотя я где-то видел это раньше).

Так кто-нибудь знает или имеет какие-то подсказки?

Благодарность


person Robert Gould    schedule 12.03.2009    source источник
comment
любая платформа действительно, обе винды, линукс плюс солярис. Мне нужно знать, какие дополнительные определения добавить для правильной компиляции.   -  person Robert Gould    schedule 16.03.2009


Ответы (7)


Настоятельно не рекомендуется:

Есть ли версия TBB, которая предоставляет статически связанные библиотеки?

TBB не предоставляется как статически связанная библиотека по следующим причинам *:

Большинство библиотек работают локально. Например, БПФ Intel (R) MKL преобразует массив. Неважно, сколько существует копий БПФ. Множественные копии и версии могут без труда сосуществовать. Но некоторые библиотеки управляют ресурсами всей программы, такими как память и процессоры. Например, сборщики мусора управляют распределением памяти в программе. Аналогичным образом TBB контролирует планирование задач в программе. Чтобы выполнять свою работу эффективно, каждый из них должен быть одиночным; то есть иметь единственный экземпляр, который может координировать действия по всей программе. Разрешение k экземпляров планировщика TBB в одной программе приведет к тому, что программных потоков будет в k раз больше, чем аппаратных потоков. Программа будет работать неэффективно, потому что машина будет переподписана в k раз, что вызовет большее переключение контекста, конкуренцию кеш-памяти и потребление памяти. Более того, эффективная поддержка вложенного параллелизма в TBB будет сведена на нет, если вложенный параллелизм возникнет из вложенных вызовов отдельных планировщиков.

Наиболее практичным решением для создания синглтона для всей программы является динамическая разделяемая библиотека, содержащая синглтон. Конечно, если бы планировщики могли сотрудничать, нам бы не понадобился синглтон. Но для этого сотрудничества требуется централизованный агент для связи; то есть синглтон!

На наше решение опустить статически подключаемую версию TBB сильно повлиял наш опыт работы с OpenMP. Как и TBB, OpenMP также пытается планировать выполнение программы. Когда-то была предоставлена ​​статическая версия среды выполнения OpenMP, и она была постоянным источником проблем, возникающих из-за дублирования планировщиков. Мы считаем, что лучше не повторять эту историю. В качестве косвенного доказательства справедливости этих соображений мы могли бы указать на тот факт, что Microsoft Visual C ++ предоставляет поддержку OpenMP только через динамические библиотеки.

Источник: http://www.threadingbuildingblocks.org/faq/11#sthash.t3BrizFQ.dpuf

person Yoav    schedule 30.10.2013
comment
Означает ли это, что при использовании общей библиотеки TBB имеет данные, которые совместно используются несколькими процессами на одном компьютере? То есть программа (где написано, что это единичный объект для всей программы) означает несколько процессов? Или это означает, что если вы статически связываете TBB, вы получите несколько синглтонов в одном процессе? Я не понимаю, как это будет работать во втором случае. - person sourcedelica; 09.08.2016
comment
Intel предоставляет build / big_iron.inc специально для создания статической библиотеки. Итак, я не думаю, что этот ответ рисует полную картину. Предложите нижеприведенный ответ sourcedelica как правильный. - person mattismyname; 09.09.2016

РЕДАКТИРОВАТЬ - изменено на extra_inc. Спасибо, Джефф!

Выполните сборку со следующим параметром:

make extra_inc=big_iron.inc

Будут созданы статические библиотеки. См. Предостережения в build/big_iron.inc.

person sourcedelica    schedule 09.08.2016

Создавайте статические библиотеки из исходного кода

Получив исходный код с 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 либо не поддерживали разделяемые библиотеки, либо плохо работали при их использовании из-за отсутствия локально смонтированной файловой системы.

person Jeff Hammond    schedule 23.10.2016

Используя версию с открытым исходным кодом:

После запуска «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

person Xin Ma    schedule 03.03.2014

Хотя это официально не одобрено командой TBB, можно создать свою собственную статически связанную версию 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:

  • Вызов g ++ с переключателем -static
  • Ссылка на tbb (-ltbb) и pthread (-lpthread)

В моем тесте мне также нужно было явно указать все .o файлы из версии TBB, созданной вручную. В зависимости от вашего проекта вам также может потребоваться передать -pthread в gcc.

Я создал игрушечный пример, чтобы задокументировать все шаги в этом репозитории Github:

Он также содержит тестовый код, чтобы убедиться, что сгенерированный двоичный файл переносится в другие дистрибутивы Linux.

person Philipp Claßen    schedule 04.06.2017


Просто свяжите файлы, просто сделал и работает. Вот файл 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')
person piotr    schedule 01.02.2012