CMake 学习笔记(OpenMP)
OpenMP是由OpenMP Architecture Review Board牵头提出的,并已被广泛接受,用于共享内存并行系统的多处理器程序设计的一套指导性编译处理方案(Compiler Directive)。简单的说就是使用 OpenMP,我们就可以不需要自己建立 线程来实现多线程并行计算。
这篇博客主要讲讲CMake 对 OpenMP 的支持。我们知道,不同的编译器开启 OpenMP 的方法是不同的。如果自己写Makefiles 或者 在 IDE 工具生成的项目文件中做设置的话就需要根据不同的编译器做不同的设置。CMake 从 3.9 版本之后开始支持 OpenMP,使用 OPenMP 变得非常简单。
下面是一个简单的使用 OpenMP 的例子程序。
#include <iostream>
#include <omp.h>
#include <string>
int main(int argc, char *argv[])
{
std::cout << "number of available processors: " << omp_get_num_procs() << std::endl;
std::cout << "number of threads: " << omp_get_max_threads() << std::endl;
auto n = std::stol(argv[1]);
std::cout << "we will form sum of numbers from 1 to " << n << std::endl;
// start timer
auto t0 = omp_get_wtime();
auto s = 0LL;
#pragma omp parallel for reduction(+ : s)
for (auto i = 1; i <= n; i++)
{
s += i;
}
// stop timer
auto t1 = omp_get_wtime();
std::cout << "sum: " << s << std::endl;
std::cout << "elapsed wall clock time: " << t1 - t0 << " seconds" << std::endl;
return 0;
}
程序很简单,for 循环那里可以开启并行。
CMake 里面有 FindOpenMP 模块,利用这个模块可以方便的开启OpenMP 功能。
下面是 CMakeLists.txt
# set minimum cmake version
cmake_minimum_required(VERSION 3.9 FATAL_ERROR)
# project name and language
project(recipe-05 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(OpenMP REQUIRED)
add_executable(example example.cpp)
target_link_libraries(example
PUBLIC
OpenMP::OpenMP_CXX
)
include(CMakePrintHelpers)
cmake_print_properties(
TARGETS
OpenMP::OpenMP_CXX
PROPERTIES
INTERFACE_COMPILE_OPTIONS
INTERFACE_INCLUDE_DIRECTORIES
INTERFACE_LINK_LIBRARIES
)
上面的代码很简单,这里只讲解几点。
- find_package(OpenMP REQUIRED) 这个是用来判断当前编译器是否支持 OpenMP 的。
- target_link_libraries(example PUBLIC OpenMP::OpenMP_CXX ) 这行告诉CMake 编译 example 时需要开启 OpenMP 支持。就这一行就够了。包括编译器选项,头文件位置,链接哪些库文件都会设置好。
再往后的内容不是必须的,我们想看看编译器选项、头文件位置等信息。CMake 有个模块 CMakePrintHelpers 可以帮我输出这些信息。
首先要包含这个模块。然后用 cmake_print_properties( ) 函数来输出我们希望看到的信息。
include(CMakePrintHelpers)
cmake_print_properties(
TARGETS
OpenMP::OpenMP_CXX
PROPERTIES
INTERFACE_COMPILE_OPTIONS
INTERFACE_INCLUDE_DIRECTORIES
INTERFACE_LINK_LIBRARIES
)
在我的电脑上输出的结果是这样的。
-- The CXX compiler identification is MSVC 19.36.32535.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.36.32532/bin/Hostx64/x64/cl.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found OpenMP_CXX: -openmp (found version "2.0")
-- Found OpenMP: TRUE (found version "2.0")
--
Properties for TARGET OpenMP::OpenMP_CXX:
OpenMP::OpenMP_CXX.INTERFACE_COMPILE_OPTIONS = "$<$<COMPILE_LANGUAGE:CXX>:-openmp>"
OpenMP::OpenMP_CXX.INTERFACE_INCLUDE_DIRECTORIES = <NOTFOUND>
OpenMP::OpenMP_CXX.INTERFACE_LINK_LIBRARIES = <NOTFOUND>
-- Configuring done (3.1s)
-- Generating done (0.0s)
如果用 MSYS2 MINGW64 工具链。则输出结果如下:
-- Building for: Ninja
-- The CXX compiler identification is GNU 13.1.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: D:/msys64/mingw64/bin/c++.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found OpenMP_CXX: -fopenmp (found version "4.5")
-- Found OpenMP: TRUE (found version "4.5")
--
Properties for TARGET OpenMP::OpenMP_CXX:
OpenMP::OpenMP_CXX.INTERFACE_COMPILE_OPTIONS = "$<$<COMPILE_LANGUAGE:CXX>:-fopenmp>"
OpenMP::OpenMP_CXX.INTERFACE_INCLUDE_DIRECTORIES = <NOTFOUND>
OpenMP::OpenMP_CXX.INTERFACE_LINK_LIBRARIES = "D:/msys64/mingw64/lib/libgomp.dll.a;D:/msys64/mingw64/lib/libmingwthrd.a;D:/msys64/mingw64/lib/libmingwthrd.a"
-- Configuring done (5.3s)
-- Generating done (0.0s)
从这个结果来看, gcc 支持的 OpenMP 版本要比 VS 高一些。