Bob*_*Bob 7 gcc openmp intel-mkl libgomp
我需要弄清楚我可以提供给gcc的编译器/链接器指令,以便在指定-fopenmp时它不会自动链接libgomp.
原因是我正试图建立英特尔的MKL BLAS.MKL需要添加单独的英特尔库来处理多线程(例如,libmkl_intel_thread或libmkl_gnu_thread).但是,用于链接MKL和libgomp的库并不适用于包括我在内的每个操作系统.这迫使我链接libmkl_intel_thread,而libmkl_intel_thread又必须链接libiomp5.
虽然我能够构建我的包,但是一些二进制文件链接到libgomp和libiomp5.我不积极,这是造成问题,但也出现了一些事故,联动组合是可疑的,即使它不会导致崩溃的肯定是一个可怕的低效率.
我正在尝试使用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.
谢谢.
GCC不支持链接到英特尔OpenMP运行时库.GCC的内部代码转换器将OpenMP指令转换为ligomp特定的调用,并且那些API的方式与公开的方式不同libiomp.此外,将两个单独的OpenMP运行时混合到一个可执行文件中(或者,如果动态加载启用OpenMP的模块,则将其混合到单个进程中)是一种灾难.这就是为什么MKL的多线程驱动程序有两种版本 - 英特尔和GNU.某些机器上缺少后者可能是安装的缺陷.
编辑:显然英特尔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
...
Run Code Online (Sandbox Code Playgroud)
在这种情况下,你要做的是:
-fopenmp编译代码时保持一致,以便GCC识别OpenMP编译指示并将代码转换为相应的调用libgomp;-fopenmp在链接阶段将选项传递给它; 相反,通过-L/path/to/libiomp5 -liomp5;-lgomp为-liomp5.如果无法进行上述更改,那么英特尔论坛上的主题就会有所帮助,因为链接器解析了链接时符号引用的方式,尽管它实际上更像是一个黑客攻击.传递-Wl,--as-needed强制GNU ld不会DT_NEEDED在命令行上为其-lgomp后面的任何库发出标记,除非该库满足未定义的符号引用,假设GCC驱动程序将在用户提供的选项之后插入某处.这个想法是防止libgomp与可执行文件链接,即使没有未解析的引用GOMP_...,这通常不应该是这种情况,因为所有引用,甚至是来自动态加载模块的引用都应该满足libiomp5.防止libgomp被RTLD加载是必不可少的,因为它中有一些构造函数例程被调用,无论是否导入符号,以及那些可能干扰IOMP的事情.
链接器技巧不适用于OS X等非ELF系统.Mach-O链接编辑器不支持,--as-needed但可能有不同的机制在该OS上实现相同的结果.
我想此时我已经有了答案;我和英特尔的人进行了多次交流,我想分享一下结果。这是他们的一些建议和我自己提出的建议的混合:
简短的回答是,你不能。Gcc 希望在链接器阶段强制使用 libgomp。如果 libiomp 也被链接,那么两个库都会被链接。哪一个会被称为?我不知道。
更长的答案是,在某些发行版上,可以通过创建自定义 libgomp.spec 或更改随 gcc 安装的 libgomp.spec 来更改 gcc 的默认行为(每当设置 -fopenmp 时添加 libgomp)。在我的发行版(自制程序)上,这是不可行的;“libgomp.spec”文件是空的,libgomp 的规范是内置于 gcc 中的。所有这些都必须被覆盖。每当 gcc 更新时都必须重做。
在某些操作系统上,可以将 libgomp 的每个副本和链接替换为 libiomp5 的符号链接。然后,二进制文件将有多个链接指向同一个库,但有两个不同的名称。那会发生什么?我不知道。
我最终做的是从 gcc 转向 llvm 的 clang-omp 实现。除非另有说明,否则它使用 libiomp5。我对此的担忧是我的项目的一部分使用了 fortran,并且没有 llvm fortran 编译器。但事实证明,即使将 -fopenmp 赋予 gfortran,只要 llvm 最终进行链接,它就会清除对 libgomp 的任何引用并用 libiomp5 替换它们。clang-omp 还可以选择使用 -fopenmp=[libiomp5|libgomp] 选择 omp 库,但我无法使其始终如一地工作。不管怎样,llvm 3.5 的 clang-omp 实现几乎覆盖了所有的 openmp 规范,到目前为止,切换中似乎没有丢失任何东西。事实上性能有所提高。
作为记录,我尝试使用 Dragonegg 使用 gfortran 作为 llvm 前端。这本书得不偿失。Dragonegg 与 gcc 4.9 不兼容,因此它强制使用 gcc 4.8。设置起来很困难;随着版本的变化,似乎很难维护;llvm 人员不确定 Dragonegg 将获得多少支持;无论如何,性能都不如仅使用 llvm。
促使我来到这里的问题是如何获得一个包含 C 和 fortran 组件的包,该包使用 OpenMP,针对 MKL 进行编译,我的操作系统的 MKL 库与 iomp5 硬链接,并且不接受 gomp。答案是唯一可行的选择是从 gcc 迁移到 clang-omp。
这确实留下了一个问题,“iomp5 是否与 gcc 4.9 '直接兼容'”,正如 OpenMP 网站上声称的那样。答案很简单,“不”,iomp5 和 gcc 4.9 不会相互兼容——至少在不对工具链进行实质性修改的情况下,没有可用的指导或文档,也不清楚是否有人这样做过成功地。
| 归档时间: |
|
| 查看次数: |
5332 次 |
| 最近记录: |