2009-03-12 9 views
14

Wie kann ich die intel's TBB libraries statisch mit meiner Anwendung verknüpfen? Ich kenne all the caveats wie unfaire Lastverteilung des Schedulers, aber ich brauche nicht den Scheduler, nur die Container, so ist es in Ordnung.Wie statisch auf TBB verlinken?

Wie auch immer ich weiß, dass dies getan werden kann, obwohl es undokumentiert ist, aber ich kann einfach nicht den Weg finden, es jetzt zu tun (obwohl ich es vorher irgendwo gesehen habe).

Also weiß jemand oder irgendwelche Hinweise?

dank

+0

jede Plattform wirklich, sowohl Windows, Linux, plus Solaris. Ich muss wissen, welche zusätzlichen Definitionen für eine korrekte Kompilierung hinzugefügt werden müssen. –

Antwort

1

Leider scheint es nicht möglich zu sein: From TBB site..
Ein Vorschlag auf dem Intel-Forum war, es manuell zu kompilieren, wenn Sie wirklich die statische Verbindung benötigen: From Intel Forum.

+1

Es ist möglich. Sie weigern sich einfach, es zu dokumentieren, weil sie nicht wollen, dass irgendjemand es macht. – Jeff

-1

Verbinden Sie einfach die Dateien, ich habe es einfach gemacht und funktioniert. Hier ist die SConscript-Datei. Es gibt zwei Nebensächlichkeiten, ein Symbol, das in tbb und tbbmalloc den gleichen Namen hat, von dem ich verhindern musste, dass es mehrfach definiert ist, und ich verhinderte die Verwendung von ITT_NOTIFY, da es in beiden Bibliotheken ein weiteres Symbol mit demselben Namen erzeugt.

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') 
4

Dies wird dringend empfohlen, nicht:

Gibt es eine Version von TBB, die Bibliotheken statisch gelinkte bietet?

TBB ist nicht als statisch gelinkte Bibliothek zur Verfügung gestellt, aus den folgenden Gründen *:

Die meisten Bibliotheken vor Ort arbeiten. Zum Beispiel transformiert eine Intel (R) MKL FFT ein Array. Es ist irrelevant, wie viele Kopien der FFT es gibt. Mehrere Kopien und Versionen können problemlos nebeneinander bestehen. Einige Bibliotheken steuern jedoch programmweite Ressourcen wie Speicher und Prozessoren. Zum Beispiel steuern Speicherbereiniger die Speicherzuweisung in einem Programm. In analoger Weise steuert TBB die Planung von Aufgaben in einem Programm. Um ihre Arbeit effektiv zu erledigen, muss jeder von ihnen ein Singleton sein; Das heißt, Sie haben eine einzige Instanz, die Aktivitäten über das gesamte Programm hinweg koordinieren kann. Wenn k Instanzen des TBB-Schedulers in einem einzigen Programm zugelassen würden, würden k-mal so viele Software-Threads wie Hardware-Threads vorhanden sein. Das Programm würde ineffizient arbeiten, da die Maschine um einen Faktor von k überzeichnet wäre, was zu mehr Kontextwechsel, Cache-Konkurrenz und Speicherverbrauch führen würde. Darüber hinaus würde TBBs effiziente Unterstützung für verschachtelte Parallelität negiert werden, wenn verschachtelte Parallelität von verschachtelten Aufrufen verschiedener Scheduler herrührte.

Die praktischste Lösung zum Erstellen eines programmweiten Singleton ist eine dynamische gemeinsam genutzte Bibliothek, die das Singleton enthält. Wenn die Disponenten zusammenarbeiten könnten, würden wir natürlich kein Singleton brauchen. Diese Kooperation erfordert jedoch die Kommunikation eines zentralen Agenten. das ist ein Singleton!

Unsere Entscheidung, eine statisch verknüpfbare Version von TBB wegzulassen, wurde stark von unserer OpenMP-Erfahrung beeinflusst. Wie TBB versucht OpenMP auch, über ein Programm zu planen. Eine statische Version der OpenMP-Laufzeit wurde einmal bereitgestellt, und es war eine ständige Quelle von Problemen, die von doppelten Schedulern herrührten. Wir denken, dass es am besten ist, diese Geschichte nicht zu wiederholen. Als indirekter Beweis für die Gültigkeit dieser Überlegungen können wir darauf hinweisen, dass Microsoft Visual C++ nur OpenMP-Unterstützung über dynamische Bibliotheken bietet.

Quelle: http://www.threadingbuildingblocks.org/faq/11#sthash.t3BrizFQ.dpuf

+1

Bedeutet dies, dass TBB bei Verwendung einer gemeinsam genutzten Bibliothek Daten enthält, die für mehrere Prozesse auf demselben Computer freigegeben sind? Das heißt, ein "Programm" (wo es "programmweit Singleton" bedeutet) bedeutet mehrere Prozesse? Oder bedeutet es, dass wenn Sie TBB statisch verknüpfen, dass Sie mehrere Singletons in einem einzigen Prozess erhalten? Ich verstehe nicht, wie es im zweiten Fall funktionieren würde. – sourcedelica

+2

Intel bietet build/big_iron.inc speziell zum Erstellen einer statischen Bibliothek. Also, ich denke nicht, dass diese Antwort das vollständige Bild zeigt. Schlagen Sie die Antwort von SourceDelica unten als die richtige vor. – mattismyname

2

Mit der Open-Source-Version:

Nach dem Ausführen von "make TBB", gehen Sie auf die build/linux_xxxxxxxx_release Ordner.

Dann laufen:

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 

Und Sie sollten libtbb.a als Ausgabe erhalten.

Beachten Sie, dass Ihr Programm sowohl mit "-ldl" bauen sollte und libtbb.a

5

EDIT - Changed extra_inc zu verwenden. Danke Jeff!

Bauen mit dem folgenden Parameter:

make extra_inc=big_iron.inc 

Die statischen Bibliotheken gebaut werden. Siehe die Vorbehalte in build/big_iron.inc.

3

Erstellen statischen Bibliotheken von der Quelle

Nach den Quellcode von https://www.threadingbuildingblocks.org/ erwerben, bauen TBB wie folgt aus:

make extra_inc=big_iron.inc

Wenn Sie zusätzliche Optionen benötigen, dann statt wie diese bauen:

make extra_inc=big_iron.inc <extra options>

Ausführung mehrerer TBB-Programme ms pro Knoten

Wenn Sie eine Multiprocessing-Anwendung ausführen, z. Wenn Sie MPI verwenden, müssen Sie möglicherweise den TBB-Scheduler explizit mit der entsprechenden Anzahl von Threads initialisieren, um eine Überbelegung zu vermeiden.

Ein Beispiel dafür in einer großen Anwendung finden Sie in https://github.com/m-a-d-n-e-s-s/madness/blob/master/src/madness/world/thread.cc.

Kommentar zu Dokumentation

Diese Funktion ist seit vielen Jahren zur Verfügung (mindestens seit 2013), obwohl sie nicht für die in anderen Antworten beschriebenen Gründe dokumentiert.

Historische Anmerkung

Diese Funktion wurde ursprünglich entwickelt, weil IBM Blue Gene und Cray Supercomputer entweder nicht gemeinsam genutzte Bibliotheken unterstützen oder auch nicht durchführen, wenn sie, aufgrund des Fehlens eines lokal eingebundenen Dateisystem verwenden.

1

Obwohl nicht offiziell vom TBB-Team empfohlen, ist es möglich, eine eigene statisch verknüpfte Version von TBB mit make extra_inc=big_iron.inc zu erstellen.

Ich habe es nicht unter Windows oder MacOS getestet, aber unter Linux, es funktionierte (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 

Die erzeugten Dateien sind in tbb-2017_U6/build/linux*release.

Wenn Sie verknüpfen Sie Ihre Anwendung auf die statische TBB Version:

  • Anruf g ++ mit dem -static Schalter
  • Verbindung gegen TBB (-ltbb) und pthread (-lpthread)

In meinem Test , Ich musste auch explizit alle .o Dateien von der manuell erstellten TBB-Version beziehen. Abhängig von Ihrem Projekt müssen Sie möglicherweise auch -pthread an gcc übergeben.

ich ein Spielzeug Beispiel erstellt habe alle Schritte in dieser Github-Repository zu dokumentieren:

Es enthält auch Testcode, um sicherzustellen, dass die erzeugte binäre auf anderen Linux tragbar ist Verteilungen.