【问题标题】:Setting maximum static alignment in Eigen from CMake从 CMake 在 Eigen 中设置最大静态对齐
【发布时间】:2021-12-25 06:12:44
【问题描述】:

我正在编写一个通用 CMake 脚本,该脚本在使用 Eigen 编译项目时提供了有关激活矢量化功能的感激回退策略。

使用带有 C++17 标准的 Eigen 3.4 并使用更新的编译器(例如 gcc > 7)进行编译,开发人员无需遵守有关静态对象对齐的代码要求。 STL 容器中不再有 EIGEN_MAKE_ALIGNED_OPERATOR_NEW 宏和显式对齐(我们在实验室为此欢呼!)。

但我们有各种各样的项目,具有不同的编译设置。我们希望在 CMake 脚本检测架构+编译功能并停用 Eigen 对架构的不安全矢量化功能时(即使这意味着破坏 abi 兼容性)编写代码而不用担心对齐问题。

有没有办法在 CMake 级别检索架构最大对齐大小,以正确设置 EIGEN_MAX_STATIC_ALIGN_BYTES 指令??

也许是一个检索 max_align_t 的 bash 脚本? https://en.cppreference.com/w/cpp/types/max_align_t

【问题讨论】:

    标签: c++ cmake eigen3


    【解决方案1】:

    您可以将https://en.cppreference.com/w/cpp/types/max_align_t 的源代码与try_run 一起使用。注意交叉编译需要额外的考虑;有关更多信息,请参阅try_run 的文档。

    cmake_tests/alignment_check.cpp:

    这是https://en.cppreference.com/w/cpp/types/max_align_t的来源

    #include <iostream>
    #include <cstddef>
    int main()
    {
        std::cout << alignof(std::max_align_t) << '\n';
    }
    

    CMakeLists.txt

    ...
    
    try_run(MY_MAXALIGN_RUN_RESULT MY_MAXALIGN_COMPILE_SUCCESS
            ${CMAKE_CURRENT_BINARY_DIR} "${CMAKE_CURRENT_SOURCE_DIR}/cmake_tests/alignment_check.cpp"
            COMPILE_OUTPUT_VARIABLE MY_MAXALIGN_COMPILE_OUTPUT
            RUN_OUTPUT_VARIABLE MY_MAXALIGN_RUN_OUTPUT)
    
    if (NOT MY_MAXALIGN_COMPILE_SUCCESS)
        message(FATAL_ERROR "Error during compilation of ${CMAKE_CURRENT_SOURCE_DIR}/cmake_tests/alignment_check.cpp :\n\n${MY_MAXALIGN_COMPILE_OUTPUT}")
    endif()
    
    if (MY_MAXALIGN_RUN_RESULT)
        message(FATAL_ERROR "Error running logic in ${CMAKE_CURRENT_SOURCE_DIR}/cmake_tests/alignment_check.cpp :\n\n${MY_MAXALIGN_RUN_OUTPUT}")
    endif()
    
    string(STRIP ${MY_MAXALIGN_RUN_OUTPUT} MY_MAXALIGN)
    
    message(STATUS "MY_MAXALIGN = \"${MY_MAXALIGN}\"")
    
    ...
    

    MY_MAXALIGN cmake 变量的内容可用于例如指定编译定义。

    CMake 输出

    ...
    MY_MAXALIGN = "8"
    ...
    

    【讨论】:

      【解决方案2】:

      虽然 fabian 的想法很棒,但它有一个 巨大 缺点 - 您必须运行可执行文件。 Not always can you run the executable。目标是获得alignof(std::max_align_t) 的值不运行任何东西,只需要编译。我们可以做到。

      一如既往,向最优秀的人学习。来自CMake modules 检查文件:CMakeCompilerABI.hCMakeCCompilerABI.cCMakeDetermineCompilerABI.cmake。请注意CMakeCompilerABI.h 如何将信息嵌入到可执行文件中,而不是实际打印它。采取同样的方法。您的源文件如下所示:

      // determineAlingofMax.cpp
      #include <cstddef>
      #define VAL  alignof(std::max_align_t)
      const char info_alingof_max_align_t[] = {
          'I', 'N', 'F', 'O', ':', 'a', 'l', 'i', 'n', 'g', 'o', 'f', 'm', 'a', 'x'
          '[', '0' + ((VAL / 10) % 10), '0' + (VAL % 10), ']', '\0',
      };
      int main(int argc, char *argv[]) {
         return  info_alingof_max_align_t[argc];
      }
      

      请注意我们如何计算 alignof 并将其转换为字符串在编译时

      现在我们必须将它编译成一个目标文件——我们不需要运行任何可执行文件。所以我们看看CMakeDetermineCompilerABI.cmake,写类似:

      set(BIN "${CMAKE_BINARY_DIR}/determineAlingofMax.bin"
      try_compile(ALIGNMAX_COMPILED
        ${CMAKE_BINARY_DIR}
        SOURCES /path/to/the/determineAlingofMax.cpp
        CMAKE_FLAGS ${CMAKE_FLAGS}
                    # Ignore unused flags
                    "--no-warn-unused-cli"
        COMPILE_DEFINITIONS ${COMPILE_DEFINITIONS}
        COPY_FILE "${BIN}"
        COPY_FILE_ERROR copy_error
        OUTPUT_VARIABLE OUTPUT
      )
      if (ALIGNMAX_COMPILED AND not copy_error)
         file(STRINGS "${BIN}" data REGEX "INFO:alingofmax\\[[^]]*\\]")
         if (data MATCHES "INFO:alingofmax\\[0*([^]]*)\\]")
             set(ALINGOFMAX "${CMAKE_MATCH_1}" CACHE INTERNAL "")
         endif()
      endif()
      if (NOT ALINGOFMAX) 
         message(FATAL_ERROR some error here)
      endif()
      # and finally, maybe option()
      set(EIGEN_MAX_STATIC_ALIGN_BYTES ${ALINGOFMAX})
      

      注意二进制文件是如何不被执行的——只被编译。字符串 INFO:alignofmax 必须足够唯一,因此它不会出现在可执行文件中的任何位置 - 我最近更喜欢使用 UUID。

      【讨论】:

      • 真的很有帮助!检查 CMake 模块是一个不错的技巧,它可以立即工作!在cmake脚本的第一行末尾缺少')',我使用${CMAKE_CXX_FLAGS}而不是${CMAKE_FLAGS},'AND not'应该是'AND NOT'否则我会出错;并且有一个错字:它是'align'而不是'aling'。谢谢!!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-11-20
      • 1970-01-01
      • 1970-01-01
      • 2015-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多