試した環境
- Windows 10
- Microsoft Visual Studio Community 2019 Version 16.8.6
- cmake 3.20.1
- g++ 9.3.0
本題
Visual Studio では OpenMP で並列化をする際にはビルドフラグ/openmp
が必要ですが、omp_get_num_thread()
などの OpenMP の API はこのビルドフラグがなくてもビルドエラーなどにはならず、値も適当な値が返ってきます。
確認のために試したソースコードは以下のとおりです。
#include <iostream> #include <omp.h> int main(int argc, char *argv[]) { std::cout << "omp_get_max_thread() = " << omp_get_max_threads() << std::endl; std::cout << "omp_get_num_thread() = " << omp_get_num_threads() << std::endl; std::cout << "omp_get_thread_num() = " << omp_get_thread_num() << std::endl; #pragma omp parallel for for (int i = 0; i < 32; ++i) { #pragma omp critical { std::cout << "i = " << i << " : omp_get_num_thread() = " << omp_get_num_threads() << " omp_get_thread_num() = " << omp_get_thread_num() << std::endl; } } return 0; }
上記ソースコードを以下の内容のCmakeLists.txtでビルドします。
/openmp
フラグを付けないときには最後の4行をコメントアウトします。
cmake_minimum_required(VERSION 3.5.1) project(omp_project) if(MSVC) string(REPLACE "/W3" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4 /EHsc") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /DBUILD_TYPE=\\\"Debug\\\"") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /DBUILD_TYPE=\\\"Release\\\"") else() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DBUILD_TYPE=\\\"Debug\\\"") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DBUILD_TYPE=\\\"Release\\\"") endif() add_executable(omp_project main.cpp) find_package(OpenMP REQUIRED) if(OpenMP_FOUND) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") endif()
実行結果は以下のとおりです。
/openmp
フラグを付けなかったときでもomp_get_max_thread()
は実行環境の論理プロセッサ数の8を返し、
omp_get_num_thread()
が1スレッドで動いていることを表しています。
/openmp
フラグを付けてビルドしたとき。
$ omp_project.exe omp_get_max_thread() = 8 omp_get_num_thread() = 1 omp_get_thread_num() = 0 i = 20 : omp_get_num_thread() = 8 omp_get_thread_num() = 5 i = 21 : omp_get_num_thread() = 8 omp_get_thread_num() = 5 i = 22 : omp_get_num_thread() = 8 omp_get_thread_num() = 5 i = 23 : omp_get_num_thread() = 8 omp_get_thread_num() = 5 i = 16 : omp_get_num_thread() = 8 omp_get_thread_num() = 4 i = 17 : omp_get_num_thread() = 8 omp_get_thread_num() = 4 i = 18 : omp_get_num_thread() = 8 omp_get_thread_num() = 4 i = 19 : omp_get_num_thread() = 8 omp_get_thread_num() = 4 i = 0 : omp_get_num_thread() = 8 omp_get_thread_num() = 0 i = 1 : omp_get_num_thread() = 8 omp_get_thread_num() = 0 i = 2 : omp_get_num_thread() = 8 omp_get_thread_num() = 0 i = 3 : omp_get_num_thread() = 8 omp_get_thread_num() = 0 i = 28 : omp_get_num_thread() = 8 omp_get_thread_num() = 7 i = 29 : omp_get_num_thread() = 8 omp_get_thread_num() = 7 i = 30 : omp_get_num_thread() = 8 omp_get_thread_num() = 7 i = 31 : omp_get_num_thread() = 8 omp_get_thread_num() = 7 i = 12 : omp_get_num_thread() = 8 omp_get_thread_num() = 3 i = 13 : omp_get_num_thread() = 8 omp_get_thread_num() = 3 i = 14 : omp_get_num_thread() = 8 omp_get_thread_num() = 3 i = 15 : omp_get_num_thread() = 8 omp_get_thread_num() = 3 i = 4 : omp_get_num_thread() = 8 omp_get_thread_num() = 1 i = 5 : omp_get_num_thread() = 8 omp_get_thread_num() = 1 i = 6 : omp_get_num_thread() = 8 omp_get_thread_num() = 1 i = 7 : omp_get_num_thread() = 8 omp_get_thread_num() = 1 i = 24 : omp_get_num_thread() = 8 omp_get_thread_num() = 6 i = 25 : omp_get_num_thread() = 8 omp_get_thread_num() = 6 i = 26 : omp_get_num_thread() = 8 omp_get_thread_num() = 6 i = 27 : omp_get_num_thread() = 8 omp_get_thread_num() = 6 i = 8 : omp_get_num_thread() = 8 omp_get_thread_num() = 2 i = 9 : omp_get_num_thread() = 8 omp_get_thread_num() = 2 i = 10 : omp_get_num_thread() = 8 omp_get_thread_num() = 2 i = 11 : omp_get_num_thread() = 8 omp_get_thread_num() = 2
/openmp
フラグを付けずにビルドしたとき。
$ omp_project.exe omp_get_max_thread() = 8 omp_get_num_thread() = 1 omp_get_thread_num() = 0 i = 0 : omp_get_num_thread() = 1 omp_get_thread_num() = 0 i = 1 : omp_get_num_thread() = 1 omp_get_thread_num() = 0 i = 2 : omp_get_num_thread() = 1 omp_get_thread_num() = 0 i = 3 : omp_get_num_thread() = 1 omp_get_thread_num() = 0 i = 4 : omp_get_num_thread() = 1 omp_get_thread_num() = 0 i = 5 : omp_get_num_thread() = 1 omp_get_thread_num() = 0 i = 6 : omp_get_num_thread() = 1 omp_get_thread_num() = 0 i = 7 : omp_get_num_thread() = 1 omp_get_thread_num() = 0 i = 8 : omp_get_num_thread() = 1 omp_get_thread_num() = 0 i = 9 : omp_get_num_thread() = 1 omp_get_thread_num() = 0 i = 10 : omp_get_num_thread() = 1 omp_get_thread_num() = 0 i = 11 : omp_get_num_thread() = 1 omp_get_thread_num() = 0 i = 12 : omp_get_num_thread() = 1 omp_get_thread_num() = 0 i = 13 : omp_get_num_thread() = 1 omp_get_thread_num() = 0 i = 14 : omp_get_num_thread() = 1 omp_get_thread_num() = 0 i = 15 : omp_get_num_thread() = 1 omp_get_thread_num() = 0 i = 16 : omp_get_num_thread() = 1 omp_get_thread_num() = 0 i = 17 : omp_get_num_thread() = 1 omp_get_thread_num() = 0 i = 18 : omp_get_num_thread() = 1 omp_get_thread_num() = 0 i = 19 : omp_get_num_thread() = 1 omp_get_thread_num() = 0 i = 20 : omp_get_num_thread() = 1 omp_get_thread_num() = 0 i = 21 : omp_get_num_thread() = 1 omp_get_thread_num() = 0 i = 22 : omp_get_num_thread() = 1 omp_get_thread_num() = 0 i = 23 : omp_get_num_thread() = 1 omp_get_thread_num() = 0 i = 24 : omp_get_num_thread() = 1 omp_get_thread_num() = 0 i = 25 : omp_get_num_thread() = 1 omp_get_thread_num() = 0 i = 26 : omp_get_num_thread() = 1 omp_get_thread_num() = 0 i = 27 : omp_get_num_thread() = 1 omp_get_thread_num() = 0 i = 28 : omp_get_num_thread() = 1 omp_get_thread_num() = 0 i = 29 : omp_get_num_thread() = 1 omp_get_thread_num() = 0 i = 30 : omp_get_num_thread() = 1 omp_get_thread_num() = 0 i = 31 : omp_get_num_thread() = 1 omp_get_thread_num() = 0
おまけ
ちなみに g++ では上記のコードは-fopenmp
フラグをつけなければビルドが通りませんでした。
$ g++ -fopenmp ../main.cpp -o omp_test.exe $ g++ ../main.cpp -o omp_test.exe C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/9.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\msys64\tmp\ccLqi92o.o:main.cpp:(.text+0x31): undefined reference to `omp_get_max_threads' C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/9.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\msys64\tmp\ccLqi92o.o:main.cpp:(.text+0x65): undefined reference to `omp_get_num_threads' C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/9.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\msys64\tmp\ccLqi92o.o:main.cpp:(.text+0x99): undefined reference to `omp_get_thread_num' C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/9.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\msys64\tmp\ccLqi92o.o:main.cpp:(.text+0xf6): undefined reference to `omp_get_num_threads' C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/9.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\msys64\tmp\ccLqi92o.o:main.cpp:(.text+0x117): undefined reference to `omp_get_thread_num' collect2.exe: error: ld returned 1 exit status