Hadoop C++单词统计

转自:http://www.pluscn.net/?p=789

Hadoop 提供了两种方式来运行C++程序, Hadoop流Pipes.

流方式:

1、 首先编写map程序(map.cpp)

#include <string>

#include <iostream>

using namespace std;
int main()

{
        string line;

         while(cin>>line)//如果是中文的话,用fgets(char*, int n, stdin)读进来,再分词处理

         {
                   cout<<line<<"\t"<<1<<endl;
         }

         return 0;
}

>>g++ -o map map.cpp

2、 编写reduce程序(reduce.cpp)

#include <map>
#include <string>
#include <iostream>
using namespace std;

int main()
{
         string key;

         string value;

         map<string,int> word_count;

         map<string,int> :: iterator it;

         while(cin>>key)

         {
                   cin>>value;

                   it= word_count.find(key);

                   if(it!= word_count.end())

                   {

                            ++(it->second);
                   }

                   else

                   {
                          word_count.insert(make_pair(key,1));
                   }
         }

         for(it= word_count.begin(); it != word_count.end(); ++it)

                   cout<<it->first<<"\t"<<it->second<<endl;

         return 0;

}

>>g++ -o reduce reduce.cpp

3、 需要统计的文件,并提交至hadoop中

File1.txt:hello hadoop helloworld

File2.txt:this is a firsthadoop

>>hadoop fs –put File1.txt File2.txt  ans

 4 、运行程序

>>hadoop jar /data/users/hadoop/hadoop/contrib/streaming/hadoop-streaming-0.20.9.jar  -file map -file reduce -input ans/* -output output1 -mapper /data/name/hadoop_streaming/map -reducer /data/name/hadoop_streaming/reduce


Pipes方式:

1、编写程序(wordcount.cpp)

#include<algorithm>
#include<limits>
#include<string>
#include"stdint.h"
#include"hadoop/Pipes.hh"
#include"hadoop/TemplateFactory.hh"
#include"hadoop/StringUtils.hh"
usingnamespace std;

class WordCountMapper:publicHadoopPipes::Mapper
{
public:
    WordCountMapper(HadoopPipes::TaskContext&context){}
    void map(HadoopPipes::MapContext& context)
    {
       string line =context.getInputValue();
       vector<string>word = HadoopUtils::splitString(line, " ");
       for (unsignedint i=0; i<word.size(); i++)
       {
           context.emit(word[i],HadoopUtils::toString(1));
       }
    }
};
class WordCountReducer:publicHadoopPipes::Reducer
{
public:
    WordCountReducer(HadoopPipes::TaskContext&context){}
    void reduce(HadoopPipes::ReduceContext& context)
    {
       int count = 0;
       while (context.nextValue())
       {
           count +=HadoopUtils::toInt(context.getInputValue());
       }

       context.emit(context.getInputKey(),HadoopUtils::toString(count));
    }
};

int main(int argc, char **argv)
{
    returnHadoopPipes::runTask(HadoopPipes::TemplateFactory<WordCountMapper,WordCountReducer>());
}

2、编写makefile

CC = g++

HADOOP_INSTALL =../../data/users/hadoop/hadoop/

PLATFORM = Linux-amd64-64

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

wordcount:wordcount.cpp

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

3、编译程序并且放入hadoop系统

> make wordcount
> hadoop fs –put wordcount name/worcount

4、运行程序

> hadoop pipes -conf ./job_config.xml -input/user/hadoop/name/input/* -output /user/hadoop/name/output -program/user/hadoop/name/wordcount


      这个例子很简单,只是统计词频。可以将MapReduce程序看成普通的C++程序,要初始化东西,放到构造函数,具体处理放到Map和Reduce里。

另外关于Streaming与Pipes的区别,有如下总结:

1、Streaming是Hadoop提供的一个可以使用其他编程语言来进行MapReduce来的API,因为Hadoop是基于Java(由于作者比较擅长Java,Lucene和Nutch都是出于Hadoop的作者)。Hadoop Streaming并不复杂,其只是使用了Unix的标准输入输出作为Hadoop和其他编程语言的开发接口,因此在其他的编程语言所写的程序中,只需要将标准输入作为程序的输入,将标准输出作为程序的输出就可以了。在标准的输入输出中,key和value是以tab作为分隔符,并且在reduce的标准输入中,hadoop框架保证了输入的数据是经过了按key排序的。

2、Hadoop Pipes是Hadoop MapReduce的C++接口。与使用标准输入输出的Hadoop Streaming不同(当然Streaming也可以用于C++),Hadoop Pipes在tasktacker和map/reduce进行通信时使用的socket作为管道,不是标准输入输出,而不是JNI。Hadoop Pipes不能运行在standalone模式下,所以要先配置成pseudo-distributed模式,因为Hadoop Pipes依赖于Hadoop的分布式缓存技术,而分布式缓存只会在HDFS运行的时候才会支持。与Java的接口不一样,Hadoop Pipes的key和value都是基于STL的string,因此在处理时开发人员需要手动地进行数据类型的转换。

3、从本质上 hadoop pipes 和 hadoop streaming 做的事情几乎一样,除了两者的通信不同,pipes 可以利用 hadoop 的 counter 特性。与 Java native code 比较,Java native code 可以使用实现了 Writable 接口的任何数据类型作为 key/value,而 pipes 和 streaming 就必须通过字符串进行一次转换(通信开销大,存储开销大)。也许正是这个原因,pipes 可能以后会被从 hadoop 中移除。当然,如果计算代价较高,可能 Java native code 并没有 C++ 执行效率高,那么以后可能就写 streaming code 了。pipes 使用的是 byte array,正好可以用 std:string 封装,只是例子里面都是转换成为字符串输入输出。这要求程序员自己设计合理的输入输出方式(数据 key/value 的分段)。


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值