miscellaneous

此处收录了一些常用的服务器使用技巧。

VIM 编辑器

为了编写脚本方便,可以直接使用服务器系统的 VIM 编辑器进行对脚本的编辑。

使用

$ vim <文件名>

可以新建或者打开已有的文本文件。

VIM 编辑器一共有两个主要的编辑模式:普通模式和插入模式。进入 VIM 编辑器后,编辑器处于普通模式。

在普通模式下,VIM 编辑器会将按键解释成命令。

  • :q 如果未修改数据,退出

  • :q! 取消所有修改,退出

  • :wq 保存并退出

  • :x 保存并退出,效果和 :wq 相同

  • :qa! 关闭当前打开的所有文件,退出

  • :<数字> 直接跳转到指定的行

  • :tabe <文件名> 新建或打开一个新文件,并以标签形式显示在编辑器上方

  • gt 切换到下一个标签

  • gT 切换到上一个标签

  • x 删除当前位置字符

  • dd 删除当前行(实际是复制到了剪贴板处)

  • <数字>dd 删除指定数目的行数

  • dw 删除当前光标所在单词

  • d$ 删除当前光标所在位置至行尾的内容

  • yy 复制当前行

  • <数字>yy 复制指定数目的行数

  • yw 复制当前光标所在单词

  • y$ 复制当前光标所在位置至行尾的内容

  • p 将剪贴板的内容粘贴至当前位置

  • i 进入插入模式,且插入位置在光标后方

  • u 撤销上一步的更改

  • Ctrl-Z 暂时离开 ViM 编辑器,回到 Shell 界面。在 Shell 中使用 fg 命令即可返回 VIM

在插入模式下,即可插入文本到光标的位置。按下 Esc 键即可返回普通模式。

使用 MEX 文件

MEX 文件在 MATLAB & C 混合编程的过程当中占据了重要角色。由于 MATLAB 不擅长处理循环,因此如果使用 MATLAB 做纯循环效率会很低下。用户可以通过将 C 程序封装成 MATLAB 可执行的文件来为 MATLAB 计算加速。

注:以下操作实例仅适用于 MATLAB R2015b 或更低的版本

以下举一个简单的例子来说明 MEX 是如何工作的。设想我们要实现这样的一个效果:输入一个矩阵 A,而后计算每个元素的 2 倍,然后返回结果。

首先,我们准备一下所需的 C 语言代码。

simple_mult.c
#include "mex.h"

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
  int i, m, n;
  double *a, *b;

  if (nrhs != 1){
    mexErrMsgTxt("Usage: B = simple_mult(A)");
    return;
  }

  m = mxGetM(prhs[0]);
  n = mxGetN(prhs[0]);
  a = mxGetPr(prhs[0]);

  plhs[0] = mxCreateDoubleMatrix(m, n, mxREAL);
  b = mxGetPr(plhs[0]);

  for (i = 0; i < m * n; ++i)
    b[i] = 2 * a[i];

}

以上代码中有以下几点是 MEX 文件的约定:

  • 必须包含头文件 mex.h,这个头文件声明了 MEX 所有的函数原型和宏。

  • 作为 MEX 文件执行的主函数,它的函数头必须为例子中的形式。函数名必须为 mexFunction;返回类型为 void;参数有四个,其中 nlhsnrhs 分别表示返回值数量和参数数量,plhsprhs 分别表示相应数量的 mxArray 指针数组。如果函数头编写不正确则 MEX 编译器无法识别。

  • 不能直接对 mxArray* 类型的数据进行操作,需要用一系列函数将其内部数据暴露出来。

  • MATLAB 中的矩阵存储格式采用 Fortran 方式,将二维矩阵存成一维长向量,先存第一列,再存第二列,以此类推。

不同 MATLAB 版本支持的 C 编译器不同。例如 MATLAB R2015b 最高只能支持 gcc-4.7 的编译器。因此在执行编译之前,请确保正在使用的 gcc 版本被 MATLAB 支持。 例如,输入

$ gcc -v

即可查看当前使用 gcc 的版本。如果不符合要求,需要使用 module 命令进行模块的替换。

进入 MATLAB 命令行模式(可使用命令 matn)。在 MATLAB 命令行下,输入

>> mex -setup C

接下来使用

>> mex simple_mult.c

即可编译 MEX 文件,其中 simple_mult.c 为源文件名,必须在当前工作目录之下。

编译成功后,MATLAB 会生成对应的 MEX 可执行文件。在我们的例子里,MATLAB 会生成一个名为 simple_mult.mexa64 的文件。使用此 MEX 函数的方法是

B = simple_mult(A)

小提示

Linux 用户可尝试将本地生成的 mexa64 文件上传至服务器,Windows/Mac用户则需要在服务器上编译 mex 文件。在Windows/Mac系统下生成的 mex 文件无法在 Linux 系统下使用。不过,仍然推荐 Linux 用户在服务器上重新编译 mex 文件,以防止运行环境变化导致程序无法运行。

设置 Intel MKL 编译选项

使用 Intel MKL 进行计算时,需要使用 gcc/g++ 编译工具,并将 MKL 库链接到你的目标文件上。

编译所需的命令行较为复杂,推荐使用Intel® Math Kernel Library Link Line Advisor来指导编译和链接。

MKL Link Line Advisor 工具需要用户指定选项才可正确完成链接命令的生成。各个选项的含义如下:

  • Select Intel product: Intel MKL 2017,选择这个选项即可。MKL 链接的命令在各个版本中的区别不大。

  • Select OS: 一定要选择 Linux,这是服务器的操作系统。

  • Select usage model of Intel Xeon Phi Coprocessor: 选择 None 即可,我们暂时用不到这个特殊的设定。

  • Select compiler: 根据个人使用的编译器自行选择。例如程序使用 gcc 编译,则此项需要选择 GNU C/C++

  • Select architecture: 选择 Intel 64,我们的系统是 64 位系统。

  • Select dynamic or static linking: 选择库类型,是静态库还是动态库。一般情况下建议选择动态库 dynamic,极少数情况(例如编译 MATLAB 的 MEX 文件)可能需要静态库 static

  • Select interface layer: 选择整数类型。在这里我们选 32-bit integer,即 32 位整数。

  • Select threading layer: 选择多线程类型。这里需要注意自己程序的用途,如果希望 MKL 仅仅占用 1 个 CPU 核心进行运算,那么需要选择 Sequential。如果希望 MKL 自动利用线程进行并行运算,那么需要选择 OpenMP threading

  • Select OpenMP library: 在上一个选项选择 OpenMP threading 之后出现,选择 OpenMP 所使用的库。在这里需要选择编译器对应版本的 OpenMP 库。例如使用 gcc 编译器进行编译,则需要选择 GNU(libgomp)

  • Select cluster library: 如果没有使用分布式并行计算的库,无需勾选任何选项。

  • Select MPI library: 无需设置。

  • Select the Fortran 95 interfaces: 无需设置。

  • Link with Intel MKL libraries explicity: 建议勾选以查看详细的链接命令。

按照如上设置完毕后,即可在下方的输出中看到链接选项和编译选项。直接复制到 Makefile 中即可。