0

我正在寻找一种方法来管理一些在构建时需要不同模块的超级计算集群上运行的一些研究代码。

例如:Server1 使用英特尔编译器和 MKL 库。Server2 使用带有 blas 和 lapack 库的 gcc 编译器。

这些差异会更改一些头文件并在某些地方(例如)进行int替换,但最终代码通常保持不变并且应该产生相同的结果(在数值噪声范围内)。MKL_INT

这是一个活跃的代码库,我会定期更改零碎。目前我在 github 上有项目,从 Server1 创建了一个 master 分支,然后是两个名为 Server1 和 Server2 的新分支;修改了每个分支中的代码,以便它们按预期编译和运行并将更改推送到上游。

作为 git 新手,我在这里碰壁了。我现在是否能够使用此模型来处理一般代码(例如在工作分支上)并将这些更改合并到两个服务器分支?如果是这样,主分支本质上会变得无用吗?有没有更好的方法来处理这种情况?

4

1 回答 1

4

我宁愿建议使用预处理器宏来模块化您的代码,以便获取正确的头文件和数据类型名称。

尽管您可以使用 git 来执行此操作,但对于您想要实现的目标,工作流程并不会真正有效。您将花费大量时间来回合并和解决冲突。

  • 让我们假设您有 2 种独立的配置类型(您应该也可以轻松扩展到 2 种以上)。要定义选项并包含特定于它们中的任何一个的标头,您可以使用以下代码结构:

    #if defined(CONFIG_SERVER_1)
    
    /* include any Server1 specific headers */
    /* Define any Server1 specific macros */
    
    #elif defined(CONFIG_SERVER_2)
    
    /* include any Server2 specific headers */
    /* Define any Server2 specific macros */
    
    #else
    
    #error "One of CONFIG_SERVER_1 or CONFIG_SERVER_2 must be defined"
    
    #endif
    
  • 您可以通过CONFIG_SERVER_1CONFIG_SERVER_2从您的 Makefile 传递:

    HOST_NAME := $(shell hostname)
    
    ifeq ($(HOST_NAME),Server1)
    CPPFLAGS += -DCONFIG_SERVER_1=1
    else
    ifeq ($(HOST_NAME),Server2)
    CPPFLAGS += -DCONFIG_SERVER_2=1
    else
    $(error Unsupported host)
    endif
    endif
    
  • 尽可能利用编译器宏(使代码将来可移植)。例如,如果您想使用MKL_INTfor ICCintforGCC并且不支持任何其他编译器,您可以这样做:

    #if defined(__INTEL_COMPILER)
    #define MY_INT MKL_INT
    
    #elif defined(__GNUC__)
    #define MY_INT int
    
    #else
    #error "Unsupported compiler!!!"
    
    #endif
    

    确保MY_INT在您计划使用的任何地方使用intMLK_INT.

    __PGIPGCC、 LLVM 等也有类似的宏__llvm__。查看页面以获取更多此类编译器特定的宏。顺便说一句,这里有一些陷阱,比如ICC最终定义__GNUC__总是可以访问一些 gcc 特定的包含。因此,对于上述用例,请确保在检查 gcc 之前检查所有其他编译器。

  • 当您拥有更多数量的源文件时,将此类宏包含在可由项目的其余部分包含的通用头文件中将使您的生活更轻松。

于 2013-03-26T02:51:14.543 回答