我有一个使用OpenMP的C++程序,它将在多台计算机上运行,这些计算机可能已经安装了OpenMP,也可能没有安装。
如何让我的程序知道一台计算机是否没有安装OpenMP,并忽略那些#include <omp.h>
、OpenMP指令(例如#pragma omp parallel ...
)和/或库函数(例如tid = omp_get_thread_num();
)?
OpenMP编译会添加预处理器定义"_OPENMP",因此您可以进行以下操作:
#if defined(_OPENMP)
#pragma omp ...
#endif
有关示例,请参见http://bisqwit.iki.fi/story/howto/openmp/#Discussion和随后的代码。
-Wno-unknown-pragmas
进行编译,出于这个原因。问题是:可能会影响项目中的其他指令,并移除有用的警告。 - johan d#if defined(_OPENMP) tid = omp_get_thread_num(); #else tid = 0; #endif
其中,_OPENMP 宏的定义状态决定了代码是执行 omp_get_thread_num() 还是赋值为0。 - KRoy#pragma
指示,这是语法的全部意义。而在非并行系统上,openmp.h
中定义的函数具有简单且明确定义的含义——特别地,头文件将检查编译器是否定义了ENABLE_OPENMP
,如果未启用,则提供正确的回退。所以,你只需要一个openmp.h
的副本来链接即可。这里有一个:http://cms.mcc.uiuc.edu/qmcdev/docs/html/OpenMP_8h-source.html。
但相关代码的部分只是这个:#if defined(ENABLE_OPENMP)
#include <omp.h>
#else
typedef int omp_int_t;
inline omp_int_t omp_get_thread_num() { return 0;}
inline omp_int_t omp_get_max_threads() { return 1;}
#endif
最坏情况下,你可以将这三行代码放入一个虚拟的openmp.h
文件中,并使用它。剩下的部分就可以正常工作了。
#pragma
语义。-1 对于 ENABLE_OPENMP
,它不符合标准。请使用 _OPENMP
。 - YvesgereYENABLE_OPENMP
的参考吗?我在预处理器定义中找不到它。请参见What preprocessor define does -fopenmp provide?。 - jwwclang++ -fopenmp
告诉我_OPENMP未定义。 - ArneOpenMP是编译器运行时的东西,而不是平台的东西。
也就是说,如果您使用Visual Studio 2005或更高版本编译应用程序,则始终可以使用OpenMP,因为运行时支持它。(如果最终用户没有安装Visual Studio C运行时,则您的应用程序将无法工作)。
所以,您不需要担心,如果您可以使用它,它将始终存在,就像strcmp等函数一样。为确保他们有CRT,您可以安装Visual Studio可再发行版。
编辑:
好的,但GCC 4.1将无法编译您的openMP应用程序,因此问题不在目标机器上,而在目标编译器上。由于所有编译器都具有预定义的宏来给出其版本,请使用#ifdef块包装您的OpenMP调用。例如,GCC使用3个宏来标识编译器版本,__GNUC__,__GNUC_MINOR__和__GNUC_PATCHLEVEL__
#include <omp.h>
,OpenMP指令(例如#pragma omp parallel ...
)和/或库函数(例如tid = omp_get_thread_num();
)?#pragma omp simd
而引起的错误报告。有条件的编译
在支持预处理器的实现中,_OPENMP宏名称被定义为十进制值yyyymm,其中yyyy和mm是实现所支持的OpenMP API版本的年份和月份。
现代的 Microsoft 编译器似乎只支持 OpenMP 从 2000 年至 2005 年之间的某个时间段。我只能说“某个时间段”,因为 OpenMP 2.0 发布于 2000 年,而 OpenMP 2.5 发布于 2005 年。但是 Microsoft 宣传了一个来自 2002 年的版本。
以下是一些 _OPENMP
数字...
所以如果你想使用,比如说 #pragma omp simd
来保护一个循环,并且 #pragma omp simd
在 OpenMP 4.0 中可用,那么:
#if _OPENMP >= 201307
#pragma omp simd
for (size_t i = 0; i < 16; ++i)
data[i] += x[i];
#else
for (size_t i = 0; i < 16; ++i)
data[i] += x[i];
#endif
这个程序将在多台机器上运行,这些机器可能已经安装了OpenMP,也可能没有安装。
需要明确的是,您可能需要在每台机器上构建您的程序。x86_64 ABI不能保证x86、x32或x86_64机器上都可用OpenMP。我也没有看到您可以在一台机器上构建,然后在另一台机器上运行的信息。
#pragma omp simd if(_OPENMP >= 201307)
和其古老的2002年OpenMP实现是可行的吗?当我尝试在Visual Studio 2015中使用它时,我收到了*test.cpp(8): error C3001: 'simd': expected an OpenMP directive name
*的错误提示。 - jww_OPENMP
,那么#pragma omp
也无法理解,因此在这种情况下if
语句将没有任何效果。您还说有合理的理由不使用#pragma
,但是您链接的文章是关于#pragma once
而不是完全不同的#pragma omp
,而且您的解决方案仍然使用了#pragma omp
。没有#pragma omp
就无法使用OpenMP功能。 - Jake Lishman