c++ - 将 OpenMP 与 -fopenmp 和 -lgomp 链接起来的区别

标签 c++ openmp static-linking dlopen

最近几天我一直在努力解决一个奇怪的问题。我们使用 GCC 4.8 创建了一些库,这些库静态链接了它们的一些依赖项 - 例如。 log4cplus 或提升。对于这些库,我们使用 boost-python 创建了 Python 绑定(bind)。

每次这样的库使用 TLS(就像 log4cplus 在它的静态初始化中做的,或者 stdlibc++ 在抛出异常时做的 - 不仅仅是在初始化阶段)整个事情都在段错误中崩溃 - 每次线程局部变量的地址一直是0。

我尝试了一切,例如重新编译、确保使用 -fPIC、确保使用 -tls-model=global-dynamic 等。没有成功。然后今天我发现这些崩溃的原因是我们链接 OpenMP 的方式。我们使用“-lgomp”而不是仅仅使用“-fopenmp”来做到这一点。因为我改变了这个,所以一切正常 - 没有崩溃,什么都没有。很好!

但我真的很想知道问题的原因是什么。那么这两种在 OpenMP 中链接的可能性有什么区别呢?

我们这里有一台 CentOS 5 机器,我们在/opt/local/gcc48 中安装了 GCC-4.8,我们也确信来自/opt/local/gcc48 的 libgomp 以及来自/opt/local/gcc48 的 libstdc++ 已被使用那里(使用了 DL_DEBUG)。

有什么想法吗?未在 Google 上找到任何内容 - 或者我使用了错误的关键字:)

最佳答案

OpenMP 是您的代码及其执行之间的中介。每个 #pragma omp 语句都被转换为对其相应的 OpenMP 库函数的调用,仅此而已。多线程执行(启动线程、加入和同步线程等)始终由操作系统 (OS) 处理。 OpenMP 所做的只是在一个简短而友好的界面中为我们处理这些低级别的依赖于操作系统的线程调用。

-fopenmp 标志是一个高级标志,其功能不仅仅包括 GCC 的 OpenMP 实现 (gomp)。这个 gomp 库将需要更多的库来访问操作系统的线程功能。在 POSIX 兼容的操作系统上,OpenMP 通常基于需要链接的 pthread。它可能还需要实时扩展库 (librt) 才能在某些操作系统上运行,而在其他操作系统上则不需要。当使用动态链接时,一切都应该自动发现,但是当你指定-static时,我认为你已经陷入了 Jakub Jelinek 描述的情况 here .但是现在,当使用 -static 时,pthread(如果需要的话还有 rt)应该自动链接。

除了链接依赖项之外,-fopenmp 标志还会激活一些 pragma 语句处理。您可以在整个 GCC 代码(如 herehere )中看到,如果没有 -fopenmp 标志(仅通过链接 gomp 库不会触发),多个编译指示将不会转换为适当的 OpenMP 函数调用。我刚刚尝试了一些示例代码,-lgomp-fopenmp 都生成了一个链接到相同库的工作可执行文件。在我的简单示例中,唯一的区别是 -fopenmp 有一个 -lgomp 没有的符号:GOMP_parallel@@GOMP_4.0+(代码 here)这是初始化并行部分的函数,该部分执行我的示例代码中 #pragma omp parallel 请求的 fork 。因此,-lgomp 版本没有将 pragma 转换为对 GCC 的 OpenMP 实现的调用。两者都生成了一个可运行的可执行文件,但在这种情况下,只有 -fopenmp 标志生成了一个并行可执行文件。

总而言之,GCC 需要 -fopenmp 来处理所有 OpenMP pragma。没有它,您的并行部分将不会 fork 任何线程,这可能会造成严重破坏,具体取决于完成内部代码的假设。

关于c++ - 将 OpenMP 与 -fopenmp 和 -lgomp 链接起来的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22938238/

相关文章:

c++ - 为什么我的字符串的开头消失了?

c - 通过 SSE/AVX 使用 OpenMP 减少

c++ - 限制来自链接对象的全局符号的范围

linux - 使用 CMAKE 编译静态可执行文件

python - 多线程数组处理,然后写入结果数组以进行 C-Python 扩展

c++ - Snow Leopard 上的 wxWidgets 问题

c++ - 使用 new 创建 vector 是否安全?

c++ - Header 中的类尚未声明

c++ - 不改变大小的数组指针。我需要锁吗?

c - 前缀和的并行化 (Openmp)