GraphLab是CMU(卡耐基梅隆大学)开发的一个以vertex为计算单元的大规模图处理系统,是继google的Pregel之后的第一个开源的大规模图处理系统,它解决了传统mapreduce框架对于机器学习应用的处理中最突出的两个问题(频繁迭代计算和大量节点通信)引起的计算效率的问题,与Haloop,Twister等基于mapreduce批量处理不同的是,它采用Pregel的以vertex为计算单元,并将机器学习抽象成GAS(gather,apply,scatter)三个步骤,然后按该抽象模型设计实现算法,事实已经证明该框架对于机器学习这一类跟图处理关系紧密的应用有很好的效果。
最近这几天在实验室集群上搭建了GraphLab分布式计算环境。这篇文章主要总结一下搭建过程和碰到的问题。
1)介绍一下实验室集群的环境。
集群中总共有9台机器,每台机器有CPU核4个,内存8G。每台机器上都安装了64位Ubuntu 12.04 Desktop版操作系统。注意,根据GraphLab官方安装指南(We require a 64-bit operating system.),要安装GraphLab,操作系统必须是64位的。
2)为每台机器安装GraphLab的依赖库。在每台机器上运行如下的命令:
sudo apt-get install gcc g++ build-essential libopenmpi-dev openmpi-bin default-jdk cmake zlib1g-dev git
3) 从GitHub上下载GraphLab。选取集群中的一台机器,进入要安装GraphLab的目录,使用如下的git命令下载GraphLab。
cd ~ # 我将GraphLab安装在了主目录下 git clone https://github.com/graphlab-code/graphlab.git
由于GraphLab项目比较大,下载需要花费一定的时间。下载完成之后,会在当前目录下看到一个名为graphlab的文件夹。
4) 编译GraphLab。
进入graphlab文件夹,使用graphlab自带的configure脚本配置编译环境:
cd graphlab
./configure
配置成功后会在graphlab文件夹内生成release和debug两个新的目录。这两个目录分别对应不同项目的发行版和测试版,在这两个目录中都可以编译GraphLab的所有Toolkit,分别对应发行版和测试版。编译后发行版与测试版的不同是,发行版在编译过程中程序都做了优化,运行速度更快。因此,我的编译选择在release目录中进行。
还有一点需要特别指出,GraphLab不仅提供了分布式大规模图计算模型,而且基于该模型实现了很多实用的工具集,这些工具集可以分成六类:主题建模、图分析、聚类、协同过滤、图模型和计算机视觉。可以根据自己的需要只编译其中的某一类或几类。如果全部编译,第一次编译时会下载很多的库文件,耗费很长时间。我只对其中的图分析工具集比较感兴趣,所以只编译了这一个。同时我也编译了apps目录中的相应样例代码。
编译release目录下的apps子目录:
cd release/apps make -j 3
第二行中的参数-j 3是利用了make的并行编译特性,3指的是同时进行三个编译任务。该数字越大,并行性越高,编译速度越快,但是占用内存也越多。如果该数字过大,会因内存不够用而使编译过程卡住。
编译release目录下的toolkits中的graph_analytics:
cd release/toolkits/graph_analytics make -j 3
如果希望编译整个GraphLab,那么可以在release目录下运行如下命令:
cd release make -j 3
5) 配置SSH。
GraphLab要求集群中任意两台机器之间能够实现SSH无密码登录。
首先要确保每台机器上都已经安装了openssh-server:
sudo apt-get install openssh-server
接着在每台机器上生成公钥和私钥对,一路回车即可:
ssh-keygen -t rsa
最后是配置任意两台机器间的无密码ssh登录。比如A和B两台机器,若要在A上能够无密码ssh登录到B,可以在A上运行如下命令:
ssh-copy-id hostname-of-B
其中hostname-of-B指的是B的主机名。
如果集群中机器数量很多,任意两台机器都配置一遍显然太麻烦了。一种简单的策略是,先配置其中一台机器到集群中所有机器的(包括ssh到自己的),然后将该台机器中$HOME/.ssh/authorized_keys文件拷贝到集群中所有其他结点上。(!!!!!这种策略经验证并不可行,还是需要手动配。!!!!!!)
6)创建machines文件并分发到集群中的所有机器上。
在集群中的某一台机器上创建一个名称为machines的文件,该文件中列出了参与计算的所有机器的主机名(或者IP地址),每个主机名占一行。将machines文件拷贝到集群中的所有机器上,注意machines文件的位置在所有机器上都要确保一致,而且必须是用户的$HOME主目录。接下来在使用GraphLab提供的脚本分发编译好的可执行文件到集群中各个机器上时,该脚本默认machines文件位于用户主目录下。
scp ~/machines hostnamex:~/
其中hostnamex是集群中其他机器的主机名。
以上步骤完成后,可以在任意一台机器上使用如下命令测试配置是否正确:
mpiexec -hostfile ~/machines hostname
如果上面的命令能够返回你在machines文件里面列出的所有主机名,那么说明配置正确。
7)分发GraphLab二进制可执行文件和相关库文件到集群中的所有机器上。
GraphLab提供了脚本用于分发编译好的二进制可执行文件到集群中的所有其他机器上。在你下载并编译了GraphLab的那台机器上,使用下面的命令来分发二进制可执行文件和相关库文件:
cd ~/graphlab/release/apps; ~/graphlab/scripts/mpirsync #分发apps
cd ~/graphlab/release/toolkits; ~/graphlab/scripts/mpirsync #分发toolkits
cd ~/graphlab/deps/local; ~/graphlab/scripts/mpirsync #分发库文件
8)单机模式下,使用模拟图运行测试PageRank程序。
在每一台机器上,运行如下的命令来测试分发到每台机器上的二进制可执行程序能否正确运行:
cd ~/graphlab/release/toolkits/graph_analytics/ ./pagerank --powerlaw=10000
如果上述命令在每台机器上都能正确无误运行,GraphLab的集群安装配置就算完成了。接下来可以测试分布式模式下能否成功运行。
9)分布式模式下,使用模拟图运行测试PageRank程序。
在任意一台机器上,运行如下命令:
cd ~ mpiexec -n 2 -hostfile machines graphlab/release/toolkits/graph_analytics/pagerank --powerlaw=100000
改变-n参数的值,多试几次,以确保安装正确无误。
如果上述命令能够正确无误执行,那么GraphLab分布式集群运算环境搭建就算完成了。
碰到的问题(目前该问题已经解决):
我在安装GraphLab后遇到的问题是:在单机模式下每台机器上PageRank都能够成功执行,但是换到分布式模式下,运行命令后程序立即卡住,没有任何错误提示信息。
这一问题让我焦虑了很多天,因为没有log,没有任何提示,根本无法定位问题所在。目前该问题仍然无法解决,与GraphLab的作者联系并交流,作者也无法定位问题所在。
我猜测机器型号可能导致该问题:
运行GraphLab的集群,每台机器的型号一定要完全一致。因为GraphLab使用C++开发,相比Java的一处编译多处运行,C++并不具有这种特性。要想让在一台机器上编译的代码能够在其他机器上正确运行,一定要确保所有机器型号一致。我碰到的现象很奇怪,虽然我集群中的机器有几台型号不一致,但是我在一台机器上编译后生成的可执行程序在型号不一样的机器上也能正常运行。但是分布式模式下,就会卡住。具体是什么原因,我也不清楚。
有人可能会问,不同型号的机器,自己编译自己的可以吗?答案是不行,分布式模式下程序运行前要检查校验码,确保所有可执行程序是在同一台机器上编译的,如果校验码不一致,程序无法运行。
但是真实情况又否定了我的这一猜测。我的集群里有三种不同型号的机器,当两台能同时运行时,这两台的型号不一样。当四台能同时运行时,其中的四台有三种型号。
问题解决方法:
通过邮件与GraphLab作者交流,作者对我碰到的问题也很费解,试了各种可能的方法,都无法解决我碰到的问题。一个偶然的机会,实验室的一位学弟解决了我的问题。我安装GraphLab使用的是OpenMPI, 学弟将OpenMPI换成MPICH后,问题解决了。关于安装MPICH的过程可以参考:http://hi.baidu.com/ldante/item/82a07c51a60da6474eff208f。