【hadoop学习】在伪分布式hadoop上实践word count程序——c/c++ pipes版本

就像上一篇博文中说的,其实最大的障碍在于hadoop自带的pipes静态库和动态库都是为linux平台的,而不是为MacOS平台的。在MacOS下,想要使用pipes,需要重新编译库文件。编译过程和方法见上一篇博文。


其他的,似乎没有太多好说的。我就列出代码吧。


hadoopWordCountPipe.cpp的内容如下:

// the header files of haddop
#include "hadoop/Pipes.hh"
#include "hadoop/TemplateFactory.hh"
#include "hadoop/StringUtils.hh"

#include <string>
#include <vector>

using namespace std;

const string WORDCOUNT = "WORDCOUNT";
const string INPUT_WORDS = "INPUT_WORDS";
const string OUTPUT_WORDS = "OUTPUT_WORDS";

class WordCountMap: public HadoopPipes::Mapper
{
public:
	HadoopPipes::TaskContext::Counter * inputWords;

	WordCountMap (HadoopPipes::TaskContext & context)
	{
		inputWords = context.getCounter(WORDCOUNT, INPUT_WORDS);
	}

	void map (HadoopPipes::MapContext & context)
	{
		vector<string> WordVec = HadoopUtils::splitString (context.getInputValue(), " ");
		for (int i=0; i<(int)WordVec.size(); i++)
			context.emit (WordVec.at(i), "1");
		context.incrementCounter (inputWords, WordVec.size());
	}
};

class WordCountReduce: public HadoopPipes::Reducer
{
public:
	HadoopPipes::TaskContext::Counter * outputWords;

	WordCountReduce (HadoopPipes::TaskContext & context)
	{
		outputWords = context.getCounter (WORDCOUNT, OUTPUT_WORDS);
	}

	void reduce (HadoopPipes::ReduceContext & context)
	{
		int sum = 0;
		while (context.nextValue())
		{
			sum += HadoopUtils::toInt (context.getInputValue());
		}
		context.emit (context.getInputKey(), HadoopUtils::toString(sum));
		context.incrementCounter (outputWords, 1);
	}
};

int main (int argc, char * argv[])
{
	return HadoopPipes::runTask (HadoopPipes::TemplateFactory<WordCountMap, WordCountReduce>());
}

还是说一下这个代码。对比《【hadoop学习】在伪分布式hadoop上手把手实践word count程序【上】》中的java代码,可以看到有一些相同的地方,也有一些不同的地方:

  1. 相同的是,都有map和reduce类,并且类中都要实现map和reduce函数;不同的是,java的类外面还套着类,通常作为jar包的名字。而pipes中c++程序,没有那么多嵌套。
  2. 不同的是,java native的hadoop程序,可以指定map和reduce的输入对儿和输出的类型,类型通常可以是Text或者LongWritable,对应字符串和整数。而pipes中,输入和输出仅仅局限于字符串类型,即便是整数值,也是以字符串进行输入和输出,然后通过函数(例如:HadoopUtils::toInt)进行转化。
  3. 不同的是,java native的hadoop程序,在map和reduce类中load资源或者初始化容器,都要在setup函数中。而pipes中,直接在c++的构造函数中了。
  4. 在pipes上述代码中,明确在构造函数中实现了counter。关于counter更多的知识,请参考《hadoop权威指南》第八章的内容。


Makefile的内容如下:

HADOOP_INSTALL="/Volumes/Data/Works/Hadoop/hadoop-0.20.2"
PLATFORM=Mac_OS_X-x86_64-64

CC = g++
CPPFLAGS = -m64 -I$(HADOOP_INSTALL)/c++/$(PLATFORM)/include 

hadoopWordCountPipe: hadoopWordCountPipe.cpp
	$(CC) $(CPPFLAGS) $< -Wall -L$(HADOOP_INSTALL)/c++/$(PLATFORM)/lib -lhadooppipes -lhadooputils -lpthread -g -O2 -o $@

注意PLATFORM变量的设置,不能是Linux-i386-32,而是新编译出来的Mac_OS_X-x86_64-64。并且CPPFLAGS中要设置"-m64"而不是"-m32",表示是编译成64位的程序。


为了在hadoop上运行,还需要一个配置文件(直接用命令行也行,不过敲起来比较麻烦)。配置文件hadoopWordCountPipeConf的内容如下:

<?xml version="1.0"?>
<configuration>
    <property>
        <name>hadoop.pipes.executable</name>
        <value>bin/hadoopWordCountPipe</value>
    </property>
    <property>
        <name>hadoop.pipes.java.recordreader</name>
        <value>true</value>
    </property>
    <property>
        <name>hadoop.pipes.java.recordwriter</name>
        <value>true</value>
    </property>
</configuration>

其中第一个属性是编译好的c/c++二进制文件hadoopWordCountPipe在hdfs中的位置。我还没有尝试用本地路径是否work。不过在运行前还是put到了hdfs上。接下来,在终端敲命令:

bin/hadoop pipes -conf /Volumes/Data/Works/hadoopWordCountPipe/hadoopWordCountPipeConf -input input -output outputPipes

主要是指定conf文件和输入输出路径。


hadoop运行并输出信息

12/10/23 22:18:14 WARN mapred.JobClient: No job jar file set.  User classes may not be found. See JobConf(Class) or JobConf#setJar(String).
12/10/23 22:18:14 INFO mapred.FileInputFormat: Total input paths to process : 1
12/10/23 22:18:15 INFO mapred.JobClient: Running job: job_201210232200_0002
12/10/23 22:18:16 INFO mapred.JobClient:  map 0% reduce 0%
12/10/23 22:18:30 INFO mapred.JobClient:  map 100% reduce 0%
12/10/23 22:18:42 INFO mapred.JobClient:  map 100% reduce 33%
12/10/23 22:18:45 INFO mapred.JobClient:  map 100% reduce 100%
12/10/23 22:18:53 INFO mapred.JobClient: Job complete: job_201210232200_0002
12/10/23 22:18:53 INFO mapred.JobClient: Counters: 20
12/10/23 22:18:53 INFO mapred.JobClient:   WORDCOUNT
12/10/23 22:18:53 INFO mapred.JobClient:     OUTPUT_WORDS=125
12/10/23 22:18:53 INFO mapred.JobClient:     INPUT_WORDS=460299
12/10/23 22:18:53 INFO mapred.JobClient:   Job Counters 
12/10/23 22:18:53 INFO mapred.JobClient:     Launched reduce tasks=1
12/10/23 22:18:53 INFO mapred.JobClient:     Launched map tasks=2
12/10/23 22:18:53 INFO mapred.JobClient:     Data-local map tasks=2
12/10/23 22:18:53 INFO mapred.JobClient:   FileSystemCounters
12/10/23 22:18:53 INFO mapred.JobClient:     FILE_BYTES_READ=4017857
12/10/23 22:18:53 INFO mapred.JobClient:     HDFS_BYTES_READ=2209727
12/10/23 22:18:53 INFO mapred.JobClient:     FILE_BYTES_WRITTEN=8035784
12/10/23 22:18:53 INFO mapred.JobClient:     HDFS_BYTES_WRITTEN=1164
12/10/23 22:18:53 INFO mapred.JobClient:   Map-Reduce Framework
12/10/23 22:18:53 INFO mapred.JobClient:     Reduce input groups=125
12/10/23 22:18:53 INFO mapred.JobClient:     Combine output records=0
12/10/23 22:18:53 INFO mapred.JobClient:     Map input records=30956
12/10/23 22:18:53 INFO mapred.JobClient:     Reduce shuffle bytes=4017863
12/10/23 22:18:53 INFO mapred.JobClient:     Reduce output records=125
12/10/23 22:18:53 INFO mapred.JobClient:     Spilled Records=920598
12/10/23 22:18:53 INFO mapred.JobClient:     Map output bytes=3097253
12/10/23 22:18:53 INFO mapred.JobClient:     Map input bytes=2207611
12/10/23 22:18:53 INFO mapred.JobClient:     Combine input records=0
12/10/23 22:18:53 INFO mapred.JobClient:     Map output records=460299
12/10/23 22:18:53 INFO mapred.JobClient:     Reduce input records=460299


在输出目录中查看结果文件内容,如下:


-1	23510
1	7446
100:1	53
101:1	79
102:1	64
103:1	613
104:1	36
105:1	23
106:1	28
107:1	67
108:1	17
109:1	26
10:1	1978
110:1	47
111:1	44
112:1	56
113:1	12
114:1	58
115:1	33
116:1	12
117:1	16
118:1	15

可以看到,内容与java版本运行出的结果一致。(参考《【hadoop学习】在伪分布式hadoop上手把手实践word count程序【下】》)。


  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值