转载

利用Distcc和Dmucs构建大规模、分布式C++编译环境(下)

上篇文章,我们介绍了如何利用 Distcc 来搭建分布式编译环境,但是 Distcc 的默认调度策略过于简单,并且并不合理。假如我们的配置是 export DISTCC_HOSTS="192.168.1.11 192.168.1.22 192.168.1.33" ,那么 Distcc 会根据 DISTCC_HOSTS 中出现的先后顺序,来安排编译任务,越靠前的机器(比如这里的 192.168.1.11 )获得越多的任务,这显然是不科学的。 因此,我们可以利用 Dmucs 提供的调度策略,来优化我们的方案。它可以根据编译机的负载情况和硬件实力,来合理的调度资源。能者多劳嘛。 为了保证本文的完整性,我们还是不厌其烦的把我们的环境再交待下: 开发机( Client ):这一台机器上有我们的项目、工程文件、代码,平时我们在这台机器上写代码,要编译的对象也在这台机器上。机器 IP192.168.1.99 服务器( Server ):负责编译的机器,一共有 3 台。 IP 分别为 192.168.1.11 , 192.168.1.22 , 192.168.1.33 . 调度器( Scheduler ):调度程序 Dmucs 所在的机器,负责把编译任务合理的派发到编译机器(服务器)的编译程序上。 IP192.168.1.88

服务器

1,安装gcc

sudo apt-get install gcc 

2,安装Distcc

sudo apt-get install distcc 
安装后可以得到两个二进制文件, distccddistcc 。前者主要负责网络数据处理,后者可以认为是 g++ 的前端,调用 g++ 进行编译。

3,配置Distcc

打开 /etc/default/distcc ,设置如下配置项:
STARTDISTCC="true"   ALLOWEDNETS="127.0.0.1 192.168.1.0/24" LISTENER="0.0.0.0" 
第一行设置开机就启动 distccd 第二行设置允许利用本机进行编译的开发机 第三行设置监听的网络

4,启动distccd

sudo service distcc start 
经过以上配置,每次机器开机,都会自动运行 distccd 。 运行如下命令确认下:
ps -aux | grep distccd 
如果看到类似的输出,说明 distccd 成功启动了。
distccd   3457  0.0  0.0   3260   144 ?        SNs  23:33   0:00 /usr/bin/distccd --pid-file=/var/run/distccd.pid --log-file=/var/log/distccd.log --daemon --allow 127.0.0.1 --listen 0.0.0.0 --nice 10 distccd   3458  0.0  0.0   3260   144 ?        SN   23:33   0:00 /usr/bin/distccd --pid-file=/var/run/distccd.pid --log-file=/var/log/distccd.log --daemon --allow 127.0.0.1 --listen 0.0.0.0 --nice 10 distccd   3461  0.0  0.0   3260   144 ?        SN   23:33   0:00 /usr/bin/distccd --pid-file=/var/run/distccd.pid --log-file=/var/log/distccd.log --daemon --allow 127.0.0.1 --listen 0.0.0.0 --nice 10 
5,安装Dmucs 首先,从 这里 下载最新版本的 Dmucs 。 安装也就是普通的 configuremakemake install ,需要注意的是,执行 make 时,需要加上参数,例如:
make CPPFLAGS=-DSERVER_MACH_NAME=///”192.168.1.88///” 
其中 192.168.1.88 是我们的调度器的机器 IP ,根据实际情况自行修改。服务器上的编译程序,需要把编译负载情况,发送给调度器上的调度程序,作为它调度时的参考信息。 如果您嫌这样麻烦,那么也可以在 make 的时候不指定选项,而是在安装后,打开 /etc/default/dmucs 文件,设置如下字段:
USE_SERVER = <192.168.1.88> 

6,启动loadavg

loadavg是安装 Dmucs 后得到的一个二进制文件,它会定期发送服务器平均负载情况给调度器,供调度程序决策之用。
sudo loadavg -s 192.168.1.88 & 
其中, 192.168.1.88 是调度程序所在机器的 IP 地址。

调度器

1,配置服务器属性 在调度器的 /usr/local/share/dmucs/ 目录下,新建 hosts-info 文件,格式和内容如下:
/#Format: machine number-of-cpus power-index 192.168.1.11       4         10 192.168.1.22       4         5 192.168.1.33       4         5 
其中, power-index (必须大于等于 1 )表示了这台机器的战斗力,值越高代表性能越强,分到的编译任务也越多。能者多劳嘛。 2,启动调度程序 命令为:
sudo service dmucs start 

开发机

1,安装Distcc

当然啦,我们假设您的开发机上已经安装 gcc 了。 2,设置编译资源 这一步是指定哪些机器(也就是上面的 Server )来负责编译工作。
export DISTCC_HOSTS="192.168.1.11 192.168.1.22 192.168.1.33" 
每台机器的 IP 之间用空格隔开。 如果机器很多,那么这样填写可能不大方便,可以在 /etc/distcc/hosts 里添加。 这两种方法可以任选一种,如果你两种都用,那么 Distcc 只认 DISTCC_HOSTS 值。

3,应用Distcc

应用 Distcc 来编译代码有几种方法: 方法一:修改 makefile 中的 CXX 的值 将 makefile 文件中的这一行
CXX = g++ 
改为
CXX = gethost distcc g++ 
然后运行 make -j18 即可。这里的 18 ,为所有服务器的 CPU Cores 的数量乘以 1.5 。上面有 3 台服务器,每台有 4 核,因此这里设置为 18 。 为了获得最优值,很可能需要反复实验、测试。 方法二:修改 configure 文件 如果您的 makefile 文件由 automake 产生,那么在运行 ./configure 时得加上参数,变为:
./configure --CXX=gethost distcc g++ 
那么生成的makefile文件将自动使用Distcc & Dmucs了。

附录:调度策略

根据 文档 , Dmucs 的调度策略是: 1, Dmucs 会维护几个列表(原文为 tier ,表示等级、阶梯),每个列表对一个 power-index ,具有相同 power-index 值的机器会在同一个列表中。因此,上面三台服务器, 192.168.1.22192.168.1.33 会在同一个列表里, 192.168.1.11 在一个列表里。 2,每次获得编译任务请求时, Dmucs 会优先从高 power-index 对应的列表里随机选一台机器。 3,如果 Dmucs 获知某台机器的平均负载过高(回忆下,该信息是服务器上的 loadavg 进程发过来的),那么会把该机器放到低一级的 power-index 对应的列表里。例如, 192.168.1.11 会被“下放”到 power-index5 对应的列表里。 4,如果某台机器的平均负载过高超过五分钟,那么该机器会被暂时雪藏,不会给它分发编译任务,直到它的负载下降到正常水平。
原文出处:http://www.yebangyu.org/blog/2015/11/30/build-distributed-compilation-env/
正文到此结束
Loading...