2009-03-12 43 views
14

¿Cómo puedo vincular estáticamente el intel's TBB libraries a mi aplicación? Sé all the caveats como distribución de carga injusta del programador, pero no necesito el planificador, solo los contenedores, así que está bien.¿Cómo enlazar estáticamente a TBB?

De todos modos, sé que se puede hacer esto, aunque no está documentado, sin embargo, parece que no puedo encontrar la manera de hacerlo ahora (aunque lo he visto antes en alguna parte).

¿Alguien sabe o tiene alguna pista?

gracias

+0

cualquier plataforma realmente, ambas ventanas, Linux, además de solaris. Necesito saber qué más define para agregar para una compilación adecuada. –

Respuesta

1

Por desgracia, no parece ser posible: From TBB site..
Una sugerencia en el foro de Intel fue compilarla manualmente si realmente necesita el enlace estático: From Intel Forum.

+1

Es posible. Simplemente se niegan a documentarlo porque no quieren que nadie lo haga. – Jeff

-1

Solo vincula los archivos, yo solo lo hice y funciona. Aquí está el archivo SConscript. Hay dos cosas menores, un símbolo que tiene el mismo nombre en tbb y tbbmalloc que tuve que evitar para ser definido de forma múltiple, y evité el uso de ITT_NOTIFY ya que crea otro símbolo con el mismo nombre en ambas librerías.

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

Esta fuerza no es recomendable:

¿Hay una versión de TBB que proporciona bibliotecas enlazadas estáticamente?

TBB no se proporciona como una biblioteca enlazado estáticamente, por las siguientes razones *:

mayoría de las bibliotecas operan a nivel local. Por ejemplo, una Intel (R) MKL FFT transforma una matriz. No importa cuántas copias de FFT haya. Varias copias y versiones pueden coexistir sin dificultad. Pero algunas bibliotecas controlan recursos de todo el programa, como memoria y procesadores. Por ejemplo, los recolectores de basura controlan la asignación de memoria en un programa. Análogamente, TBB controla la programación de tareas en un programa. Para hacer su trabajo de manera efectiva, cada uno de estos debe ser un singleton; es decir, tiene una única instancia que puede coordinar actividades en todo el programa. Permitir k instancias del planificador TBB en un solo programa provocaría que haya k veces más subprocesos de software que subprocesos de hardware. El programa funcionaría de manera ineficiente, porque la máquina se sobresuscribiría por un factor de k, causando más cambio de contexto, contención de caché y consumo de memoria. Además, el soporte eficiente de TBB para el paralelismo anidado se negaría cuando el paralelismo anidado surgiera de invocaciones anidadas de distintos planificadores.

La solución más práctica para crear un singleton en todo el programa es una biblioteca compartida dinámica que contiene el singleton. Por supuesto, si los programadores pudieran cooperar, no necesitaríamos un singleton. Pero esa cooperación requiere un agente centralizado para comunicarse; es decir, ¡un singleton!

Nuestra decisión de omitir una versión estáticamente enlazable de TBB fue fuertemente influenciada por nuestra experiencia OpenMP. Al igual que TBB, OpenMP también intenta programar en un programa. Una vez se proporcionó una versión estática del tiempo de ejecución de OpenMP, y ha sido una fuente constante de problemas derivados de los programadores duplicados. Creemos que es mejor no repetir esa historia. Como prueba indirecta de la validez de estas consideraciones, podríamos señalar el hecho de que Microsoft Visual C++ solo brinda soporte OpenMP a través de bibliotecas dinámicas.

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

+1

¿Esto significa que al usar una biblioteca compartida, TBB tiene datos que se comparten en múltiples procesos en la misma máquina? Es decir, ¿un "programa" (donde dice "singleton de todo el programa") significa procesos múltiples? ¿O significa que si vincula estáticamente TBB obtendrá múltiples singletons en un solo proceso? No entiendo cómo funcionaría en el segundo caso. – sourcedelica

+2

Intel proporciona build/big_iron.inc específicamente con el fin de crear una biblioteca estática. Entonces, no creo que esta respuesta represente la imagen completa. Sugerir la respuesta de sourcedelica a continuación como la correcta. – mattismyname

2

Usando la versión de código abierto:

Después de ejecutar "hacer TBB", vaya a la carpeta de compilación/linux_xxxxxxxx_release.

A continuación, ejecute:

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 

y usted debe obtener libtbb.a como salida.

Tenga en cuenta que el programa debe construir tanto con "-ldl" y libtbb.a

5

EDITAR - Se ha modificado para utilizar extra_inc. Gracias Jeff!

Construir con el siguiente parámetro:

make extra_inc=big_iron.inc 

se construirán las bibliotecas estáticas. Ver las advertencias en build/big_iron.inc.

3

Construir bibliotecas estáticas de la fuente

Después de adquirir el código fuente de la https://www.threadingbuildingblocks.org/, construir TBB así:

make extra_inc=big_iron.inc

Si necesita opciones adicionales, entonces en vez construir de esta manera:

make extra_inc=big_iron.inc <extra options>

Ejecución de varios programas TBB ms por nodo

Si ejecuta una aplicación de multiprocesamiento, p. utilizando MPI, es posible que deba inicializar explícitamente el planificador TBB con la cantidad adecuada de subprocesos para evitar la sobresuscripción.

Un ejemplo de esto en una aplicación grande se puede encontrar en https://github.com/m-a-d-n-e-s-s/madness/blob/master/src/madness/world/thread.cc.

comentario sobre la documentación

Esta característica está disponible desde hace muchos años (por lo menos desde 2013), aunque no está documentado por las razones descritas en otras respuestas.

Nota histórica

Esta característica se desarrolló originalmente debido a IBM Blue Gene y Cray superordenadores o bien no apoyar las bibliotecas compartidas o no funcionar bien al usarlos, debido a la falta de un sistema de archivos montados localmente.

1

Aunque oficialmente no está respaldado por el equipo TBB, es posible construir su propia versión estáticamente vinculada de TBB con make extra_inc=big_iron.inc.

Yo no lo he probado en Windows o MacOS, pero en Linux, funcionó (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 

Los archivos generados son en tbb-2017_U6/build/linux*release.

Al vincular su aplicación a la versión estática TBB:

  • Call g ++ con el interruptor -static
  • Enlace contra TBB (-ltbb) y pthread (-lpthread)

En mi prueba , También necesitaba hacer referencia explícita a todos los archivos .o de la versión TBB de compilación manual. Dependiendo de su proyecto, es posible que también deba pasar -pthread a gcc.

He creado un ejemplo de juguete para documentar todos los pasos de este repositorio de Github:

También contiene el código de prueba para asegurarse de que el binario generado es portable en otro Linux distribuciones.