c++ - tutorial - download tbb
¿Cómo enlazar estáticamente a TBB? (7)
Construye bibliotecas estáticas desde la fuente
Después de adquirir el código fuente de https://www.threadingbuildingblocks.org/ , genere TBB así:
make extra_inc=big_iron.inc
Si necesita opciones adicionales, entonces compile así:
make extra_inc=big_iron.inc <extra options>
Ejecutando múltiples programas TBB por nodo
Si ejecuta una aplicación de multiprocesamiento, por ejemplo, utilizando MPI, es posible que deba inicializar explícitamente el programador TBB con el número adecuado de subprocesos para evitar la suscripción excesiva.
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 .
Comentar sobre la documentación
Esta característica ha estado disponible durante muchos años (al menos desde 2013), aunque no está documentada por las razones descritas en otras respuestas.
Nota historica
Esta característica se desarrolló originalmente porque las supercomputadoras IBM Blue Gene y Cray no eran compatibles con las bibliotecas compartidas o no funcionaban bien al usarlas, debido a la falta de un sistema de archivos montado localmente.
¿Cómo puedo vincular estáticamente las bibliotecas TBB de Intel a mi aplicación? Conozco todas las advertencias , como la distribución injusta de la carga del programador, pero no necesito el programador, solo los contenedores, así que está bien.
De todos modos, sé que esto se puede hacer, aunque no está documentado, sin embargo, parece que no puedo encontrar la manera de hacerlo ahora (aunque lo he visto antes en algún lugar).
Entonces, ¿alguien sabe o tiene alguna pista?
Gracias
Aunque no cuenta con el respaldo oficial del equipo de TBB, es posible crear su propia versión estáticamente vinculada de TBB con make extra_inc=big_iron.inc
.
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 están en tbb-2017_U6/build/linux*release
.
Cuando vinculas tu aplicación a la versión TBB estática:
- Llame a 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 en este repositorio de Github:
También contiene código de prueba para asegurarse de que el binario generado sea portátil en otras distribuciones de Linux.
Esto no es muy recomendable:
¿Existe una versión de TBB que proporcione bibliotecas enlazadas estáticamente?
TBB no se proporciona como una biblioteca enlazada estáticamente, por las siguientes razones *:
La mayoría de las bibliotecas operan localmente. Por ejemplo, un FFT de Intel (R) MKL transforma una matriz. Es irrelevante cuántas copias de la FFT hay. Múltiples copias y versiones pueden coexistir sin dificultad. Pero algunas bibliotecas controlan los recursos de todo el programa, como la memoria y los procesadores. Por ejemplo, los recolectores de basura controlan la asignación de memoria a través de un programa. Análogamente, TBB controla la programación de tareas a través de un programa. Para hacer su trabajo de manera efectiva, cada uno de estos debe ser un singleton; es decir, tener una instancia única que pueda coordinar actividades en todo el programa. Permitir k instancias del programador TBB en un solo programa causaría que haya k veces más hebras de software que hebras de hardware. El programa funcionaría de manera ineficiente, ya que la máquina estaría sobre suscrita por un factor de k, lo que provocaría un mayor cambio de contexto, una contención de caché y el 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 programadores distintos.
La solución más práctica para crear un singleton para todo el programa es una biblioteca dinámica compartida que contenga 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ática 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 que surgen de los programadores duplicados. Pensamos 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
Lamentablemente no parece ser posible: desde el sitio TBB. .
Una sugerencia en el foro de Intel fue compilarlo manualmente si realmente necesita el enlace estático: Desde el foro de Intel .
Solo vinculo los archivos, 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 que se definiera de forma múltiple, e impidí 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'')
Usando la versión de código abierto:
Después de ejecutar "make tbb", vaya a la carpeta build / linux_xxxxxxxx_release.
Entonces corre:
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 deberías obtener libtbb.a como salida.
Tenga en cuenta que su programa debe compilar tanto con "-ldl" como con libtbb.a
EDITAR - Cambiado para usar extra_inc
. Gracias jeff
Construir con el siguiente parámetro:
make extra_inc=big_iron.inc
Se construirán las bibliotecas estáticas. Vea las advertencias en build/big_iron.inc
.