現在のコンパイラがopenmpサポートでビルドできることを確認したいと思います。アプリケーションはさまざまなUNIXシステムに展開されており、その一部には古いバージョンのOpenMPが含まれている可能性があります。重要なOpenMP機能をテストしたいと思います。そのため、OpenMP呼び出しの一部を組み込んだテストソースファイルを作成します。
したがって、非常に単純なテストファイルを作成し、CMakeのtry_compile関数を使用しようとしました。残念ながら、-fopenmpリンカーフラグを正しく適用していないようです。誰かがリンカフラグを強制する方法、またはリンカフラグがどこかに適用されているかどうかを確認する方法を知っていますか?
cMakeLists.txtから
try_compile(
HAVE_OPENMP
${APBS_ROOT}/src/config
${APBS_ROOT}/src/config/omp_test.c
CMAKE_FLAGS "-DCMAKE_C_FLAGS=-fopenmp -DCMAKE_EXE_LINKER_FLAGS=-fopenmp"
OUTPUT_VARIABLE TRY_COMPILE_OUTPUT
)
omp_test.cから
#include <stdio.h>
#include <omp.h>
int main()
{
int i;
int threadID = 0;
#pragma omp parallel for private(i, threadID)
for(i = 0; i < 16; i++ )
{
threadID = omp_get_thread_num();
#pragma omp critical
{
printf("Thread %d reporting\n", threadID);
}
}
return 0;
}
結果の出力は
Change Dir: src/config/CMakeFiles/CMakeTmp
Run Build Command:/usr/bin/make "cmTryCompileExec/fast"
/usr/bin/make -f CMakeFiles/cmTryCompileExec.dir/build.make CMakeFiles/cmTryCompileExec.dir/build
make[1]: Entering directory `src/config/CMakeFiles/CMakeTmp'
/usr/bin/cmake -E cmake_progress_report /data/work/source/apbs/src/config/CMakeFiles/CMakeTmp/CMakeFiles 1
Building C object CMakeFiles/cmTryCompileExec.dir/omp_test.c.o
/usr/bin/gcc -o CMakeFiles/cmTryCompileExec.dir/omp_test.c.o -c /data/work/source/apbs/src/config/omp_test.c
Linking C executable cmTryCompileExec
/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec.dir/link.txt --verbose=1
/usr/bin/gcc CMakeFiles/cmTryCompileExec.dir/omp_test.c.o -o cmTryCompileExec -rdynamic
CMakeFiles/cmTryCompileExec.dir/omp_test.c.o: In function `main':
omp_test.c:(.text+0x19): undefined reference to `omp_get_thread_num'
collect2: ld returned 1 exit status
make[1]: *** [cmTryCompileExec] Error 1
make[1]: Leaving directory `src/config/CMakeFiles/CMakeTmp'
make: *** [cmTryCompileExec/fast] Error 2
CMake Error at CMakeLists.txt:688 (message):
Test OpenMP program would not build. OpenMP disabled
コマンドラインでテストプログラムをコンパイルしようとすると、うまくいきます
src/config$ gcc -fopenmp omp_test.c -o omp_test && ./omp_test
Thread 1 reporting
Thread 4 reporting
Thread 7 reporting
Thread 11 reporting
Thread 9 reporting
Thread 12 reporting
Thread 6 reporting
Thread 8 reporting
Thread 15 reporting
Thread 13 reporting
Thread 10 reporting
Thread 0 reporting
Thread 3 reporting
Thread 2 reporting
Thread 5 reporting
Thread 14 reporting
CMakeには、コンパイラがOpenMPをサポートしているかどうかをテストするための 標準モジュール があります。
find_package(OpenMP)
if (OPENMP_FOUND)
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}")
endif()
注:
現在のOpenMP
バージョンのプロジェクトにCMake
を含めるために、この回答を使用することはお勧めしません。例参照 this 質問またはその他の回答。
CMake 3.9現在、言語ごとにインポートされたOpenMPターゲットがあります。私はこれがはるかにエレガントなソリューションであると考えています。 C++の例を次に示します。
cmake_minimum_required(VERSION 3.9)
project(solver LANGUAGES CXX)
find_package(OpenMP REQUIRED)
add_executable(solver solver.cc)
target_link_libraries(solver PRIVATE OpenMP::OpenMP_CXX)
これはタイピングが少ないので便利です。この方法では、エラーが発生しやすいコンパイルフラグやライブラリなどで調整する必要がありません。これが現代のCMakeの方向です。
CMake 3.9よりも古いもので作業している場合、 現在受け入れられている答え をお勧めしません。ターゲットごとにフラグを設定する方が良いと思います:
add_executable(solver solver.cc)
target_link_libraries(solver PRIVATE "${OpenMP_CXX_FLAGS}")
target_compile_options(solver PRIVATE "${OpenMP_CXX_FLAGS}")
これは、一部のコンパイラでは機能しない場合があります。これが、CMakeがCMake 3.9でOpenMPサポートを刷新した理由の1つです。
G ++で「モダン」な方法を使用する場合は、次のこともできます。
find_package(OpenMP REQUIRED)
add_executable(Foo foo.cpp)
target_compile_options(Foo PRIVATE -Wall ${OpenMP_CXX_FLAGS})
target_link_libraries(Foo PRIVATE ${OpenMP_CXX_FLAGS})
通知:
Target_compile_optionsのみを省略すると、プラグマは単純に無視されます(有効な警告が表示されます)
G ++が適切にリンクされていないため、コードがコンパイルされないtarget_link_librariesのみを残す場合
両方を省くと、1。注が適用され、リンクが不要になり、コードがコンパイルされます。
この「ハック」とフラグのリンクが他のコンパイラでも機能しているかどうかはわかりません。
OpenMPサポートはCMake 3.9+で大幅に改善されました
cmake_minimum_required(VERSION 3.9)
project(openmp_test) # you can change the project name
find_package(OpenMP)
add_executable(openmp_para_test main.cpp) # you can change the excutable name
if(OpenMP_CXX_FOUND)
target_link_libraries(openmp_para_test PUBLIC OpenMP::OpenMP_CXX)
endif()
この方法により、必要に応じてライブラリリンク行がコンパイル行とは異なるように正しく設定されます。
ソース 。