hadoop上C++开发两种方式的例子
百度在使用Hadoop过程中同样发现了Hadoop因为Java语言带来的低效问题,并对Hadoop进行扩展。
而在此之前,百度也尝试了 Hadoop PIPES 和 Hadoop Streamming,但是发现这些问题:
- 这两种方案都无法很好地控制Child JVM(Map TaskTracker和Reduce TaskTracker)内存的使用,这部分都由JVM自己控制,而你能做的就只是使用-Xmx设置内存限制而已;
- 这两种方案都只能影响到Mapper和Reducer回调函数,而真正影响性能的sort和shuffle过程依然在Java实现的TaskTracker中执行完成;
- 数据流问题。两种方案中,数据处理流都必须由TaskTracker流向Mapper或者Reducer然后再流回来。而无论是使用pipeline还是socket方式传递数据,都难以避免数据的移动。对于大规模数据处理,其代价是不可忽视的。
- TaskTracker JVM只负责少量通信工作,其内存需求很小并且可以预见,从而容易控制,譬如设为-Xmx100m就足够了;
- sort和shuffle过程都使用C++模块实现,性能得到提高;
- 数据在其整个生命周期都只在C++模块中,避免不必要的移动。
这就犹如将C++模块的战线往前推进了。当然,也许在很多人看来,这只是五十步与百步的区别,但是这多出来的五十步,
两种的方式的具体例子:
一,Pipes方式:
首先,建立相应的目录:
> hadoop fs –mkdir name
> hadoop fs –mkdir name/input
>hadoop fs –put file1.txt file2.txt name/input
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、编写配置文件(job_config.xml)
<?xml version="1.0"?>
<configuration>
<property>
<name>mapred.job.name</name>
<value>WordCount</value>
</property>
<property>
<name>mapred.reduce.tasks</name>
<value>10</value>
</property>
<property>
<name>mapred.task.timeout</name>
<value>180000</value>
</property>
<property>
<name>hadoop.pipes.executable</name>
<value>/user/hadoop/name/wordcount</value>
<description> Executable path is given as"path#executable-name"
sothat the executable will havea symlink in working directory.
This can be used for gdbdebugging etc.
</description>
</property>
<property>
<name>mapred.create.symlink</name>
<value>yes</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>
<property>
<name>mapred.child.env</name>
<value>LD_LIBRARY_PATH=/data/lib</value> <!--如果用到动态库: lib库的路径,要保证每台机器上都有 -->
<description>User added environment variables for the task tracker child
processes. Example :
1) A=foo This will set the env variable A to foo
2) B=$B:c This is inherit tasktracker's B env variable.
</description>
</property>
<property>
<name>mapred.cache.files</name>
<value>/user/hadoop/name/data#data</value> <!--如果用到外部文件:hadoop上的data路径,程序中fopen("data/file.txt", "r") -->
</property>
5、运行程序
> hadoop pipes -conf ./job_config.xml -input/user/hadoop/name/input/* -output /user/hadoop/name/output -program/user/hadoop/name/wordcount
(注:output文件夹在运行前不能建立,系统会自己建立)
这个例子很简单,只是统计词频,但是,实际的数据挖掘比较复杂,尤其涉及到中文,很多情况下要进行分词,那就要初始化一些分词句柄及空间,然后分词处理,其实可以将MapReduce程序看成普通的C++程序,要初始化东西,放到构造函数,具体处理放到Map和Reduce里。
二,Streaming方式:
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
hadoop上C++开发两种方式的例子的更多相关文章
- curl文件上传有两种方式,一种是post_fileds,一种是infile
		curl文件上传有两种方式,一种是POSTFIELDS,一种是INFILE,POSTFIELDS传递@实际地址,INFILE传递文件流句柄! );curl_setopt($ch, CURLOPT_PO ... 
- 将HTML页面自动保存为PDF文件并上传的两种方式(一)-前端(react)方式
		一.业务场景 公司的样本检测报告以React页面的形式生成,已调整为A4大小的样式并已实现分页,业务上需要将这个网页生成PDF文件,并上传到服务器,后续会将这个文件发送给客户(这里不考虑). 二.原来 ... 
- 利用Selenium实现图片文件上传的两种方式介绍
		在实现UI自动化测试过程中,有一类需求是实现图片上传,这种需求根据开发的实现方式,UI的实现方式也会不同. 一.直接利用Selenium实现 这种方式是最简单的一种实现方式,但是依赖于开发的实现. 当 ... 
- hadoop 读取文件的两种方式
		1.操作javaAPI方式 static{ URL.setURLStreamHandlerFactory(new FsUrlStreamHandlerFactory()); } public stat ... 
- ASP.NET Core 1.0中实现文件上传的两种方式(提交表单和采用AJAX)
		Bipin Joshi (http://www.binaryintellect.net/articles/f1cee257-378a-42c1-9f2f-075a3aed1d98.aspx) Uplo ... 
- FORM开发两种方式实现动态LIST
		方法一:常规的,也是网上比较常见的 1.将目标ITEM的子类信息设置为List,不需要添加列表中元素,不需要初始值. 2.新建一个Procedure,代码如下: PROCEDURE basis_lis ... 
- Java文件上传的几种方式
		文件上传与文件上传一样重要.在Java中,要实现文件上传,可以有两种方式: 1.通过Servlet类上传 2.通过Struts框架实现上传 这两种方式的根本还是通过Servlet进行IO流的操作. 一 ... 
- Hadoop之HDFS文件操作常有两种方式(转载)
		摘要:Hadoop之HDFS文件操作常有两种方式,命令行方式和JavaAPI方式.本文介绍如何利用这两种方式对HDFS文件进行操作. 关键词:HDFS文件 命令行 Java API HD ... 
- MyBatis开发Dao层的两种方式(Mapper动态代理方式)
		MyBatis开发原始Dao层请阅读我的上一篇博客:MyBatis开发Dao层的两种方式(原始Dao层开发) 接上一篇博客继续介绍MyBatis开发Dao层的第二种方式:Mapper动态代理方式 Ma ... 
随机推荐
- Bash shell中的位置参数$#,$*,$@,$0,$1,$2...及特殊参数$?,$-等的含义
			http://hi.baidu.com/lolorosa/blog/item/5775a608bd670d33b0351da7.html $# 是传给脚本的参数个数 $@ 是传给脚本的所有参数的列表 ... 
- springMVC源码分析--@ModelAttribute使用及运行原理
			这一篇博客我们简单的介绍一下ModelAttribute的使用和运行原理. 1.首先@ModelAttribute是使用在方法或者上的,当使用在方法上时其作用于本身所在的Controller,在访问C ... 
- Linux 高性能服务器编程——高性能服务器程序框架
			问题聚焦: 核心章节. 服务器一般分为如下三个主要模块:I/O处理单元(四种I/O模型,两种高效事件处理模块),逻辑单元(两种高效并发模式,有效状态机)和存储单元(不讨论). 服务器模 ... 
- 破解Oracle ERP 密码
			1. 写作目的 1 2. 利用Toad或其它pl/sql工具在Oracle ERP Database中建立Package,源码如下 1 (1). ... 
- linux源码编译安装OpenCV
			为了尽可能保证OpenCV的特性,使用OpenCV源码编译安装在linux上.先从安装其依赖项开始,以ubuntu 14.04.X为例讲解在Linux上源码编译安装OpenCV,其他linux版本可以 ... 
- T-SQL动态查询(1)——简介
			起因: 由于最近工作需要及过去一直的疑问,所以决定着手研究一下动态SQL.由于离开一线开发有点年头了,很多技巧性的东西没有过多研究,作为DBA和<SQL Server性能优化与管理的艺术> ... 
- XML之DOM解析模型
			<?xml version= "1.0" encoding = "UTF-8"> <articles> <article cate ... 
- adb -s 设备名   设备名还有非法字符
			当有多台安卓设备在同一电脑上时 想敲adb控制某一个设备 需要如下格式 adb -s 设备名 设备名 可以用adb devices获取 当发现adb devices 获取的名字是特别长而且含有非法字符 ... 
- linux shell 判断文件是否存在等符号
			-a file exists. -b file exists and is a block special file. -c file exists and is a character spec ... 
- windows下实现win32俄罗斯方块练手,编程的几点心得
			编程珠玑2阅读笔记: 1.使用c语言性能监视器,完成对代码的调优工作 2.关联数组: 拓扑排序算法,可以用于当存在遮挡的时候决定三维场景的绘制顺序. 3.小型算法中的测试与调试工具 脚手架程序:&l ... 
