构建环境
-
检测操作系统
-
在不同的操作系统上,CMake需要根据操作系统启用条件编译,就需要检测当前的操作系统;
-
进行操作系统匹配的变量为CMAKE_SYSTEM_NAME,该名称为CMAKE为操作系统定义的,使用if的条件语句可以进行操作系统的匹配,如下
if(CMAKE_SYSTEM_NAME STREQUAL "Linux") message(STATUS "Configuring on/for Linux") endif()
唯一需要注意的是,操作系统有不同的名称,如macOS对应“Darwin”;
-
为了最小化平台之间的转移成本,需要避免直接使用shell命令、还应该避免显示使用路径分隔符;
-
cmake代码只是用前斜杠作为路径分割符,cmake自动将他们转换为所所涉及的操作系统环境;
-
-
处理与平台相关的代码
-
当编写原码时,可能需要考虑到其在不同操作系统上的安装和编译,这时需要根据操作系统编译源码;
-
同样需要首先检测操作系统,然后再编译定义,如下所示:
... add_executable(hello-world hello-world.cpp) if(CMAKE_SYSTEM_NAME STREQUAL "Linux") target_compile_definitions(hello-world PUBLIC "IS_LINUX") endif() ...
即在继续之前,需要检查前面的表达式,并考虑在系统上的行为;
-
-
处理与编译器相关的源码
-
对于适应不同的编译器,我们需要在CMake中进行预定义;
-
同样的,需要在add_executable之后使用target_compile_definitions进行指定,其变量名称为COMPILE_NAME,然后使用is语句判断对应的处理器,代码如下:
... add_executable(hello-world hello-world.cpp) if(CMAKE_SYSTEM_NAME STREQUAL "Linux") target_compile_definitions(hello-world PUBLIC "$COMPILE_NAME=\"${CMAKE_CXX_COMPILER_ID}\"") endif() if(CMAKE_CXX_COMPILER_ID MATCHES Intel) target_compile_definitions(hello-world PUBLIC "IS_INTEL_COMPILE") endif() ...
-
-
检测处理器体系结构
-
检测主机的处理器指令集
-
为Eigen库使能向量化
-
处理器的向量化功能,可以提高代码的性能。如使用线性代数的Eigen C++库加速可执行文件;
-
对于如下代码而言:
#include <Eigen/Dense> EIGEN_DONT_INLINE double simple_function(Eigen::VectorXd &va, Eigen::VectorXd &vb) { // this simple function computes the dot product of two vectors // of course it could be expressed more compactly double d = va.dot(vb); return d; }
向量化可以加快simple_function中的点积操作.
-
根据Eigen库的文档,设置适当的编译器标志就足以生成向量化代码,,代码如下:
... # 使用Eigen库,需要在系统上找到其头文件 find_package(Eigen3 3.3 REQUIRED CONFIG) # 引入CheckCXXCompilerFlag.cmake标准模块文件 include(CheckCXXCompilerFlag) #检查-match=native和-xHost编译器标志是否工作 check_cxx_compiler_flag("-march-native" _march_native_works) check_cxx_compiler_flag("-xHost" _xhost_works) #设置空变量_CXX_FLAGS保存找到的两个编译器标志,如果都不起作用,则为空 set(_CXX_FLAGS) if(_march_native_works) message(STATUS "Using processor's vector instructions (-march=native compiler flag set)") set(_CXX_FLAGS "-march=native") esleif(_march_native_works) message(STATUS "Using processor's vector instructions (-xHost compiler flag set)") set(_CXX_FLAGS "_xHost") else() message(STATUS "No suitable compiler flag found for vectorization") endif() add_executable(linear-algebra linear-algebra.cpp) target_compile_options(linear-algebra PRIVATE ${_CXX_FLAGS}) #使用优化标志 target_link_libraries(linear-algebra PRIVATE Eigen3::Eigen) ...
-
工作原理:处理器大都提供向量指令集,利用这一特点可以使代码提速;
-
线性代数可以从Eigen库中获得加速,所以在使用Eigen库时,需要考虑向量化;
-
我们需要指示编译器检查处理器,为当前体系结构生成本机指令;
-
不同的编译器供应商会使用不同的标志来实现,GNU使用-march=native标志实现,Intel编译器使用-xHostsh标志是实现;
-
使用CheckCXXCompilerFlag.cmake模块提供的check_cxx_compiler_flag函数进行编译器标志的检查。其中,第一个参数为要检查的标志,第二个用于存储检查结果(true or false);
-