1. 程式人生 > >hadoop c++ pipes介面實現

hadoop c++ pipes介面實現

(1)首先我們需要知道map-reduce的基本原理,這裡不說了。其次我們需要知道,在用C++編寫hadoop應用程式時,需要包含三個標頭檔案:

#include "Pipes.hh"

#include "TemplateFactory.hh"

#include "StringUtils.hh"

這三個檔案在hadoop安裝包的 “c++\Linux-amd64-64\include\” 或 “c++\Linux-i386-32\include\” 子目錄下(根據你的作業系統是64位或32位,分別對應不同的目錄)。

既然有標頭檔案,就需要有對應的實現檔案,或者動態/靜態庫,這裡我用的是靜態庫 libhadooppipes.a 和 libhadooputils.a 。靜態庫是在Makefile中指定的,後面再說。這裡特別提醒一下大家:如果你的hadoop叢集不是隻有一臺伺服器,那麼如果你編譯時使用了任何動態庫的話,在執行的時候就要保證在別的hadoop伺服器上也能找到相應的動態庫,否則就會在hadoop JobTracker的詳細資訊中看到找不到動態庫的錯誤提示。

(2)下面來看看程式:

#include"Pipes.hh"

#include"TemplateFactory.hh"

#include"StringUtils.hh"

class DataCountMap:public HadoopPipes::Mapper {

public:

DataCountMap(HadoopPipes::TaskContext&context){}

void map(HadoopPipes::MapContext&context) {

std::vector<std::string>words=HadoopUtils::splitString(context.getInputValue()," "); // 這裡是分割字串,如前文所述,每一行資料中的各項是以空格來分割的。分割的結果儲存到了一個std::vector中

if("kkk"==words[1]) {

context.emit("kkk","1");

} else if("nnn"==words[1]) {

context.emit("nnn","1");

}

}

};

class DataCountReduce:public HadoopPipes::Reducer {

public:

DataCountReduce(HadoopPipes::TaskContext&context){}

void reduce(HadoopPipes::ReduceContext&context)

{

int sum=0;

while(context.nextValue()) {

sum++;

}

context.emit(context.getInputKey(),HadoopUtils::toString(sum));

}

};

int main(int argc,char*argv[])

{

return HadoopPipes::runTask(HadoopPipes::TemplateFactory<DataCountMap, DataCountReduce>());

}

上面的程式挺簡單的,只要你知道了map-reduce的基本原理。

一個map類,一個reduce類,一個執行任務的main函式。

map類對每一行資料進行拆分,當找到我們感興趣的“kkk”或“nnn”時,就生成一條輸出的記錄(emit函式的作用);recude類對map的資料進行彙總,這裡只是簡單地計數,所以每次+1。

(3)有了程式碼,我們接著就要編寫相應的Makefile了。我的Makefile如下:

HADOOP_INSTALL = /usr/local/hadoop

INCLUDE_PATH = $(HADOOP_INSTALL)/src/c++/

CC = g++

CXXFLAGS = -Wall -g \

-I${INCLUDE_PATH}pipes/api/hadoop \

-I${INCLUDE_PATH}utils/api/hadoop

LDFLAGS = -ljvm -lhadooppipes -lhadooputils -lpthread

OBJECTS=dz_count.o

dz_count: $(OBJECTS)

$(CC) $(CXXFLAGS) -o [email protected] $(OBJECTS) $(LDFLAGS)

其中,HADOOP_INSTALL是你的hadoop安裝路徑,其餘的 INCLUDE_PATH 等請對照你的目錄做相應更改,最後生成的可執行程式名為dz_count。這裡沒有考慮release,因為僅作簡單的說明用。

(4)有了程式碼和Makefile,就可以編譯了。編譯得到可執行程式dz_count。將其上傳到hdfs中:

hadoop fs -put dz_count /my_dir/

其中 “/my_dir/” 是你在hdfs中的目錄。

文章來源:http://www.codelast.com/

(5)下面就可以執行我們的hadoop程式了:

hadoop pipes -D hadoop.pipes.java.recordreader=true -D hadoop.pipes.java.recordwriter=true -input /data/ -output /my_dir/output -program /my_dir/dz_count

其中,-input /data/ 表明你的輸入資料(即你的源資料)所處的hdfs目錄為 /data/,-output /my_dir/output 表明你的輸出檔案目錄為 /my_dir/output,“output” 這一級目錄必須不存在(如果存在會報錯),程式執行時會生成它。-program /my_dir/dz_count 表明你要執行的程式為 /my_dir/ 目錄下的 dz_count 程式。

回車之後程式就開始執行,隨後你可以在命令列下看到它的狀態在更新,或者在hadoop JobTracker中也可以觀察到程式的執行狀態。

文章來源:http://www.codelast.com/

(6)等程式執行完後,如果任務沒有失敗的話,我們可以看到,你前面指定的hdfs輸出目錄 /my_dir/output 裡生成了一個檔案(假設其名為“part-00000”),我們就可以檢視執行結果了:

hadoop fs -cat /my_dir/output/part-00000

輸出結果形為:

kkk 178099387

nnn 678219805

表明第二項為“kkk”的資料行共有178099387條,而“nnn”則為678219805條。

順便再說一點廢話:

(1)如何中止一個hadoop任務?當你在命令列下提交了一個hadoop job後,就算你按Ctrl+C,也不能中止掉那個job,因為它已經被Jobtracker接管了。這時,你要用如下命令中止它:

hadoop job -kill Job_ID

其中,Job_ID就是你提交的job的ID,可以在Jobtracker中檢視到。

(2)一些基本概念:

map-reduce過程中,在map時,hadoop會將輸入的資料按一定的大小(例如100M,這個值是可以配置的)分為若干塊來處理,一個塊對應一個map類,也就是說,一個塊只會執行map類的建構函式一次。而每一行記錄則對應一個map()方法,也就是說,一行記錄就會執行一次map()方法。因此,如果你有什麼資訊需要輸出(例如std::cout)的話,就要注意了:如果在map()方法中輸出,則當輸入資料量很大時,可能就會輸出太多的資訊,如果可以在map的建構函式中輸出的話,則輸出的資訊會少得多。

在reduce時,對map輸出的同一個key,有一個reduce類,也就是說,無論你的同一個key有多少個value,在reduce的時候只要是同一個key,就會出現在同一個reduce類裡,在這個類裡的reduce方法中,你用 while (context.nextValue()) 迴圈可以遍歷所有的value,這樣就可以處理同一個key的N個value了。

正因為在預設情況下,相同key的記錄會落到同一個reducer中,所以,當你的key的數量比你設定的reducer的數量要少的時候,就導致了某些reducer分配不到任何資料,最終輸出的某些檔案(part-r-xxxxx)是空檔案。如果你設定的reducer數量要少於key的數量(這是最常見的情況),那麼就會有多個key落入同一個reducer中被處理,但是,每一次reduce()方法被呼叫時,其中將只包含一個key,同一個reducer裡的多個key就會導致reduce()方法被多次呼叫。

這樣,我們就完成了一個完整的C++ hadoop分散式應用程式的編寫。

來源:http://www.codelast.com/

相關推薦

hadoop c++ pipes介面實現

(1)首先我們需要知道map-reduce的基本原理,這裡不說了。其次我們需要知道,在用C++編寫hadoop應用程式時,需要包含三個標頭檔案: #include "Pipes.hh" #include "TemplateFactory.hh" #include "StringUtils.hh" 這

ros 工作空間的覆蓋、c++程式設計介面實現通訊方式、自定義訊息格式、分散式多機通訊

工作空間的覆蓋 同一個工作空間下,不允許出現同名的功能包,否則無法編譯。不同工作空間下,允許出現同名的功能包,但會出現工作空間覆蓋的現象。 ros工作空間的路徑記錄在ROS_PACKAGE_PATH環境變數中,可以通過env命令檢視計算機中的環境變數,再利用管道過濾出有關

C語言介面實現2048小遊戲

這是我在大一第二學期(兩年前)為了參加比賽,自學後寫的一個Dome,拿出來和大家分享一下,程式碼為兩年前的程式碼,未改動,優化以及各式可能很一般,請見諒。 #include "stdio.h" #include "stdlib.h" #include "time.h" #d

linux c copyFile介面實現

LINUX本身並不提供拷貝檔案的介面,於是自己實現了一個。int copyFile(const char* src, const char* des) { int nRet = 0; FILE* pSrc = NULL, *pDes = NULL; pSrc = fo

[C#]利用介面實現多型性淺析

所謂的多型性,個人認為說的是相同的程式接受幾段毫不相同的引數而能正常的執行。而在C#中利用介面實現多型性我覺得並不是太嚴謹。我認為要真正實現多型性離不開泛型。 舉個小例子: public interface Iinter { publ

c#: WinForm介面多語言簡單實現

終於有空整理下多語言實現思路。搜尋已有方案,有用不同resx檔案的,有每個控制元件動態設定的,有用反射去整的,頗為繁瑣。 結合專案中實現方法,並做簡化,實現通用的多語言切換方案,以做備忘。 它支援語言自定義新增與擴充,靈活易用,更易於維護。它以xml格式儲存語言資訊,支援自定義語言、ToolTip等字串。

C#多型(虛方法,抽象,介面實現

轉自   淺談C# 多型的魅力(虛方法,抽象,介面實現) 前言:我們都知道面向物件的三大特性:封裝,繼承,多型。封裝和繼承對於初學者而言比較好理解,但要理解多型,尤其是深入理解,初學者往往存在有很多困惑,為什麼這樣就可以?有時候感覺很不可思

C語言訪問INFORMIX資料庫 — 介面實現

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

SAP移庫介面實現C#版)

 SAP移庫介面C#版本實現程式碼如下: /// <summary> /// 移庫介面(將倉庫中的地址移到線邊倉,線邊倉的地址用模板檔名稱作為引數傳過來) /// </summary> /// <param

SAP發料介面實現C#版)

//發料介面 /// <summary> /// 根據發料單號獲取發料單內所包含的物料資訊,根據生產訂單的編號,發料至生產訂單 /// </summary> /// <param name

c語言模擬實現順序表的所有介面

順序表的c語言實現 此專案建立了3個原始檔,test.h用來建立結構體和函式的宣告,main.c用來實現函式,test.c用來實現順序表的總邏輯。 test.h #include<stdio.h> #include<assert.h> #include&

C++ Pimpl技法 C++介面實現分離原理

C++Pimpl技法 優點 將C++的介面和實現分離在兩個類中 C++的實現和介面在不同的檔案中,實現改變不會導致介面檔案重新編譯 將下面的程式碼分開在幾個檔案裡面就實現了Pimpl技法 #include <iostream> class X; c

C/C++ 中使用 TensorFlow 預訓練好的模型—— 直接呼叫 C++ 介面實現

現在的深度學習框架一般都是基於 Python 來實現,構建、訓練、儲存和呼叫模型都可以很容易地在 Python 下完成。但有時候,我們在實際應用這些模型的時候可能需要在其他程式語言下進行,本文將通過直接呼叫 TensorFlow 的 C/C++ 介面來匯入 T

C#關於介面到基類到子類繼承到方法實現的示例

  介面(interface)–>基類–>子類繼承–>方法實現;程式碼如下: class Program { static void Main(string[] args) {

C語言介面實現[+]

static char rcsid[] = "$Id: H:/drh/idioms/book/RCS/text.doc,v 1.10 1996/06/26 23:02:01 drh Exp $"; #include <string.h> #include <limits.h> #

linux c 建立多級目錄介面實現

void casMkdir(const char* dir) { int nIndex = 1; char* tmp = (char*)dir; while ( nIndex < strlen(dir) + 1 ) { if (*(dir+nIndex)

[C++] 類的"實現"與"介面"分離

C++這門語言囊括了多種語言正規化,並不是嚴格的OOP語言,所以在“實現與介面的分離”這一方面做得並不算好。 這裡簡述C++的類設計中把實現與介面分離的方法. 在C++的某個class的定義中,不僅聲明瞭介面,還可以看到實現的具體細節,當然這個視角是針

C#顯式實現介面與隱式實現介面的5個不同點

顯然我們隨時都可以建立該介面的物件,但是編譯器無法得知我們所建立的物件究竟是指向該介面的哪個實現的(如果有的話),甚至即便我們沒有實現該介面也一樣可以建立該介面的物件。簡單來說就是如果我們只是建立了介面的物件,那麼編譯器就只知道這個物件是指向該介面的,至於其餘的事情他一概不知。 相關導讀:C

讀書筆記--C語言介面實現--介面實現

介面實現 重點內容在本書中的第二章中,介紹了介面的封裝例子。 1. 介面定義 C語言中可將介面封裝好,讓後以.h檔案作文擴充套件,簡單例子: extern int Arith_max(int x, int y); extern int Ari

c語言介面實現--再論記憶體管理含例項

本章開頭指出上一章節描述的記憶體管理方法存在一些缺陷,比如不適合頻繁建立和銷燬記憶體的應用場景;所以在本章重新給出了另外一種設計思路。提出了記憶體池的概念,如果熟悉的小夥伴,還接觸過執行緒池的概念。個人認為這一章節比前一章節更好理解。 本書中的程式碼有個地方的