使用 Environment Module 管理不同版本软件

使用 Environment Modules 可以方便地管理和切换同一软件的不同版本。

一般的使用流程

要使用 module,需要:

  1. 安装 module 程序,这个直接用软件仓库安装就行了。在 CentOS 7 下,命令是 sudo yum install environment-modules 。源码编译方法参见这里#Installing)

  2. 如果是采取编译安装的,需要设置一下脚本和资源。对于 Bash 用户,创建一个 module_bashrc 文件(假设放在~/)如下(所有\<>中的路径请替换为你系统中的路径,下同):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    #----------------------------------------------------------------------#
    # system-wide bashrc #
    # functions and settings for sh-derivative shells #
    #----------------------------------------------------------------------#
    . <MODULE_INSTALL_PATH>/init/bash
    # module initialization
    #
    case "$0" in
    -sh|sh|*/sh) modules_shell=sh ;;
    -ksh|ksh|*/ksh) modules_shell=ksh ;;
    -zsh|zsh|*/zsh) modules_shell=zsh ;;
    -bash|bash|*/bash) modules_shell=bash ;;
    esac
    eval "module() { eval \`<MODULE_INSTALL_PATH>/bin/modulecmd $modules_shell \$*\`; }"
    unset modules_shell
    #----------------------------------------------------------------------#
    # set this if bash exists on your system and to use it
    # instead of sh - so per-process dot files will be sourced.
    #----------------------------------------------------------------------#
    sh() { bash "[email protected]"; }
    #----------------------------------------------------------------------#
    # further system customizations can be added here
    #
    export MODULEPATH=<MODULE_INSTALL_PATH>/modulefiles:$MODULEPATH

配置文件的最后一行指明了 module files 存放的路径,我将它们放在 module 的安装路径下了。在当前账户的 .bashrc 里加入一行 source module_bashrc 使得每次登陆的时候会初始化 module。如果是用包管理器安装的,直接在 ~/.bashrc 里加上上面的最后一行来指定其他存储 module files 的位置。

  1. 为每一个库创建一个 module file。一般来说这不比写环境变量脚本麻烦多少,主要就是标明这个库的冲突标识符(两个冲突标识符相同的 module 不能同时加载)和列出库的 PATH LD_LIBRARY_PATHMANPATH 路径。

  2. 将写好的 module files 放到 module 可以识别的目录中以供查询。同一个库不同版本的 module files 应放在同一个文件夹中,以版本号作为文件名。比如,我有 CUDA 6.0 和 CUDA 7.0,它们的 module files 我会放在/public/soft/Module/module_files/cuda 这个目录下面。如果需要指定默认加载的版本,则需要在文件夹里多创建一个 .version 文件:

    1
    2
    #%Module1.0
    set ModulesVersion "<DEFAULT_VERSION_STRING>"
  3. 可以使用 module avail 命令让系统列出可用的 module,选择需要的使用库,用 module load 命令进行加载。如果一个库有多个可选版本,需要指定加载哪一个,或者让系统加载默认选项。 以上述的 CUDA 6.0 7.0 为例,我需要加载 CUDA 7.0 的时候,则应该使用 module load cuda/7.0 的命令来加载。

  4. 要查看现在已经加载的 mofule files,可以用命令 module list 。使用完以后用 module unload 来取消加载,比如module unload cuda/7.0

我使用过的一些 Module Files

GCC

1
2
3
4
5
6
7
8
9
10
11
#%Module 1.0
# 这一行一般 module file 都有
# 冲突标识符gcc
conflict gcc
# 所需路径
prepend-path PATH <GCC_INSTALL_PATH>/bin
prepend-path LD_LIBRARY_PATH <GCC_INSTALL_PATH>/lib64
prepend-path LIBRARY_PATH <GCC_INSTALL_PATH>/lib64
prepend-path MANPATH <GCC_INSTALL_PATH>/share/man

ICC

ICC的设置比较麻烦,一般不能手动配置。Intel 官网 给出了一个方法 ,使用 env2 来捕获和创建 module file:

1
2
3
4
5
6
7
# 1. place a special comment at the beginning of the file so that module will recognize it as a module file with following command:
echo "#%Module 1.0" > <ICC_MODULE_FILE>
# 2. use the env2 command like below:
perl env2 -from bash -to modulecmd "<ICC_INSTALL_PATH>/<ICC_INSTALL_VRSION>/psxevars.sh <intel64|ia-32>" >> <ICC_MODULE_FILE>
# an example:
# perl env2 -from bash -to modulecmd "/opt/intel/parallel_studio_xe_2017.1.043/psxevars.sh intel64" >> 2017.1.043

这两步得到的 mofule files 还不能直接用,要将里面的类似 PATH MANPATH 等带有『PATH』的项,前面的类型从 setenv 改成 prepend-path

OpenMPI

Hint: 用不同的编译器编译出来的OpenMPI是不一样的,不要搞混,module files 也不要搞混了路径

1
2
3
4
5
6
#%Module 1.0
conflict mpi
prepend-path PATH <OMPI_INSTALL_PATH>/bin
prepend-path LD_LIBRARY_PATH <OMPI_INSTALL_PATH>/lib
prepend-path MANPATH <OMPI_INSTALL_PATH>/share/man

Intel MPI

1
2
3
4
5
6
7
8
#%Module 1.0
# Replace the /opt/intel in the below with your path, and the version should be correspond to your IMPI version
conflict mpi
prepend-path PATH /opt/intel/impi/2017.1.132/intel64/bin
prepend-path LD_LIBRARY_PATH /opt/intel/impi/2017.1.132/intel64/lib
prepend-path MANPATH /opt/intel/impi/2017.1.132/man
setenv I_MPI_ROOT /opt/intel/impi/2017.1.132

CUDA

1
2
3
4
5
#%Module 1.0
conflict cuda
prepend-path PATH <CUDA_INSTALL_PATH>/bin
prepend-path LD_LIBRARY_PATH <CUDA_INSTALL_PATH>/lib64