我需要找出一个可以输入 gcc 的编译器/链接器指令,以便在指定 -fopenmp 时它不会自动链接 libgomp。
原因是我正在尝试针对英特尔的 MKL BLAS 进行构建。 MKL 需要添加单独的 Intel 库来处理多线程(例如 libmkl_intel_thread 或 libmkl_gnu_thread)。然而,用于将 MKL 与 libgomp 链接的库并不是在每个操作系统上都可用,包括我的操作系统。这迫使我链接 libmkl_intel_thread,而它又必须链接到 libiomp5。
虽然我能够构建我的包,但一些二进制文件同时链接到 libgomp 和 libiomp5。我不是positive这导致了问题,但是已经发生了一些崩溃,联动组合是可疑的,即使它没有导致崩溃,它的效率也肯定是可怕的低下。
我正在尝试使用 gcc 4.9.1 来做到这一点。
不幸的是,避免使用 -fopenmp 并不是一个选择。原因是,这是为了编译一个由多个子包组成的相当大的包,其 Makefile 不是最好的形状,并且稍后可能会编译来自其他源(插件)的附加包。强制使用通用编译器/链接器指令并不困难。然而,打开 --enable-openmp 会同时激活 -fopenmp 和用于触发与多线程相关的代码的定义。尝试将这三个(--enable-openmp、-fopenmp 以及链接到 --enable-openmp 的代码)分开是不可行的。
我浏览了手册页,没有看到任何允许选择 openmp 库的 gcc 指令。英特尔的论坛有一个非常古老的讨论,他们建议在 -fopenmp 之后立即指定一个静态库,然后是 --as-needed。这看起来很不稳定,而且很有可能干扰插件包。 llvm-openmp 似乎曾经考虑过 -fopenmp=libiomp5 指令,但它似乎已在 3.5 版本中被删除,无论如何我都在尝试使用 gcc。
Thanks.
GCC 不支持链接 Intel OpenMP 运行时库。 GCC 的内部代码转换器将 OpenMP 指令转换为ligomp
- 特定的调用和那些具有与公开的 API 不同的 APIlibiomp
。此外,将两个独立的 OpenMP 运行时混合到一个可执行文件中(或者混合到单个进程中,如果支持 OpenMP 的模块是动态加载的)会导致灾难。这就是 MKL 的多线程驱动程序有两种版本的原因 - Intel 版本和 GNU 版本。某些机器上缺少后者可能是安装缺陷。
Edit:显然,Intel OpenMP 运行时提供了一个 GNU 兼容层,这意味着它可以用作libgomp
。至少有这些符号:
$ nm libiomp5.a | sort | grep GOMP_
0000000000000000 T GOMP_barrier@@VERSION
0000000000000000 T GOMP_barrier@GOMP_1.0
0000000000000000 T __kmp_api_GOMP_barrier
0000000000000000 T __kmp_api_GOMP_barrier_10_alias
...
在这种情况下,你要做的是:
- keep
-fopenmp
编译代码,以便 GCC 识别 OpenMP 编译指示并将代码转换为相应的调用libgomp
;
- 如果使用GCC来链接可执行文件或共享库,do not通过它
-fopenmp
链接阶段的选项;相反,通过-L/path/to/libiomp5 -liomp5
;
- 如果使用 GNU ld 链接可执行文件/模块,则替换
-lgomp
with -liomp5
.
如果无法进行上述更改,那么英特尔论坛上的帖子就有意义,因为链接器解析链接时符号引用的方式,尽管它实际上更像是一种黑客攻击。通过-Wl,--as-needed
强制 GNU ld 不发出DT_NEEDED
命令行上跟随它的任何库的标签,除非该库满足未定义的符号引用,假设 GCC 驱动程序将插入-lgomp
在用户提供的选项之后的某处。这个想法是为了防止libgomp
即使没有未解析的引用,也不会与可执行文件链接GOMP_...
,通常不应该是这种情况,因为所有引用,即使是来自动态加载模块的引用,都应该满足libiomp5
。预防libgomp
防止被 RTLD 加载是至关重要的,因为其中有一些构造函数例程,无论是否导入符号都会调用这些例程,并且这些例程可能会干扰 IOMP。
链接器技巧在 OS X 等非 ELF 系统上不起作用。Mach-O 链接编辑器不支持--as-needed
尽管可能有不同的机制可以在该操作系统上实现相同的结果。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)