【问题标题】:How to statically link to TBB?如何静态链接到 TBB?
【发布时间】:2009-03-12 11:50:26
【问题描述】:

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

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

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

谢谢

【问题讨论】:

  • 任何平台,包括 Windows、Linux 和 solaris。我需要知道要为正确编译添加哪些额外定义。

标签: c++ linker tbb


【解决方案1】:

强烈不建议这样做:

是否有提供静态链接库的 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#sthash.t3BrizFQ.dpuf

【讨论】:

  • 这是否意味着通过使用共享库 TBB 具有在同一台机器上的多个进程之间共享的数据?也就是说,“程序”(它说“程序范围的单例”)意味着多个进程?或者这是否意味着如果您静态链接 TBB,您将在单个进程中获得多个单例?我不明白在第二种情况下它会如何工作。
  • 英特尔提供 build/big_iron.inc 专门用于构建静态库。所以,我不认为这个答案描绘了全貌。建议以下 sourcedelica 的答案为正确答案。
【解决方案2】:

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

使用以下参数构建:

make extra_inc=big_iron.inc

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

【讨论】:

    【解决方案3】:

    从源代码构建静态库

    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 超级计算机不支持共享库,或者由于缺少本地安装的文件系统而在使用它们时性能不佳。

    【讨论】:

      【解决方案4】:

      使用开源版本:

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

      【讨论】:

        【解决方案5】:

        虽然没有得到 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 发行版上移植。

        【讨论】:

          【解决方案6】:

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

          【讨论】:

          • 有可能。他们只是拒绝记录它,因为他们不希望任何人这样做。
          【解决方案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')
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2020-07-30
            • 2015-08-24
            • 1970-01-01
            • 2011-11-02
            • 1970-01-01
            • 2010-09-30
            • 1970-01-01
            相关资源
            最近更新 更多