MR实现--矩阵乘法
import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.io.*;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.input.FileSplit;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.fs.Path;
public class matrix {
public static int rowM=0;
public static int columnM=0;
public static int columnN=0;
public static class MyMapper extends Mapper<Object, Text, Text, Text>{
private Text map_key=new Text();
private Text map_value=new Text();
public void setup(Context context){
Configuration conf=context.getConfiguration();
columnN=Integer.parseInt(conf.get("columnN"));
rowM=Integer.parseInt(conf.get("rowM"));
}
public void map(Object key,Text value,Context context) throws IOException, InterruptedException{
FileSplit fileSplit=(FileSplit)context.getInputSplit();
String filename=fileSplit.getPath().getName();
System.out.println("map的数据分片长度是:"+fileSplit.getLength());
System.out.println("数据分片的起始位置是:"+fileSplit.getStart());
String[] tempLocation=fileSplit.getLocations();
for (String string : tempLocation) {
System.out.println("数据分片所在的主机是:"+string);
}
if(filename.contains("M")){
String[] tuple=value.toString().split(",");
int i=Integer.parseInt(tuple[0]);
String[] tupleS=tuple[1].split("\t");
int j=Integer.parseInt(tupleS[0]);
int Mij=Integer.parseInt(tupleS[1]);
for (int k = 1; k <columnN+1 ; k++) {
map_key.set(i+","+k);
map_value.set("M"+","+j+","+Mij);
context.write(map_key, map_value);
}
}
else if(filename.contains("N")){
String[] tuple=value.toString().split(",");
int j=Integer.parseInt(tuple[0]);
String[] tupleS=tuple[1].split("\t");
int k=Integer.parseInt(tupleS[0]);
int Njk=Integer.parseInt(tupleS[1]);
for (int i = 1; i <rowM+1 ; i++) {
map_key.set(i+","+k);
map_value.set("N"+","+j+","+Njk);
context.write(map_key, map_value);
}
}
}
}
public static class MyReducer extends Reducer<Text, Text, Text, Text>{
private int sum=0;
public void setup(Context context) throws IOException{
Configuration conf=context.getConfiguration();
columnM=Integer.parseInt(conf.get("columnM"));
}
public void reduce(Text key,Iterable<Text> value,Context context)throws IOException,InterruptedException{
int[] M=new int[columnM+1];
int[] N=new int[columnM+1];
System.out.println(key.toString()+"对应的value列表所有值是:");
for (Text val : value){
System.out.println(val.toString());
String[] tuple=val.toString().split(",");
if(tuple[0].equals("M")){
M[Integer.parseInt(tuple[1])]=Integer.parseInt(tuple[2]);
}else {
N[Integer.parseInt(tuple[1])]=Integer.parseInt(tuple[2]);
}
}
for (int j=1;j<columnM+1;++j) {
sum+=M[j]*N[j];
}
context.write(key, new Text(Integer.toString(sum)));
sum=0;
}
}
public static void main(String[] args)throws Exception {
if(args.length!=3){
System.err.println("Usage: MatrixMultiply <inputPathM> <inputPathN> <outputPath>");
System.exit(2);
}
else{
System.out.println("M文件路径:"+args[0]);
String[] infoTupleM=args[0].split("_");
rowM=Integer.parseInt(infoTupleM[1]);
columnM=Integer.parseInt(infoTupleM[2]);
String[] infoTupleN=args[1].split("_");
columnN=Integer.parseInt(infoTupleN[2]);
}
Configuration conf=new Configuration();
conf.set("columnM", Integer.toString(columnM));
conf.set("rowM", Integer.toString(rowM));
conf.set("columnN", Integer.toString(columnN));
Job job=new Job(conf, "Matrix");
job.setJarByClass(matrix.class);
job.setMapperClass(MyMapper.class);
job.setReducerClass(MyReducer.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(Text.class);
FileInputFormat.setInputPaths(job, new Path(args[0]),new Path(args[1]));
FileOutputFormat.setOutputPath(job, new Path(args[2]));
System.exit(job.waitForCompletion(true)?0:1);
}
}
以上是j计算矩阵M*N结果的源码,总共需要三个输入参数,分别是:M矩阵的路径、N矩阵的路径以及结果的输入路径。其中M存放在文件中,文件的格式是"M_rows_columns",实验的矩阵文件是M_300_500。实验中N的文件是N_500_700。并且M和N文件中的格式都是相同的,都是"i,j\tMij"的形式,其中i表示元素所在矩阵的行数,j表示元素所在矩阵的列数,Mij表示矩阵元素。如下图所示(N_500_700中形式也是如此):

矩阵内都是随机数,矩阵文件由以下shell脚本生成:
#!/bin/bash
for i in `seq $`
do
for j in `seq $`
do
s=$(($RANDOM%))
echo -e "$i,$j\t$s" >>M_$1_$
done
done
2)map的输出形式:
假设M是i*j的矩阵,N是j*k的矩阵。
对于M矩阵:map的输出形式是(<i,k>,<"M",j,Mij>),其中<i,k>是key,<"M",j,Mij>是value。
M表示此键值对是M矩阵的内容
Mij是M矩阵中的一个元素
i和j是这个元素在矩阵中的位置
k是矩阵N的列数
对于N矩阵:map的输出形式是(<i,k>,<"N",j,Njk>),其中<i,k>是key,<"N",j,Njk>是value。
可以看到M和N经过map处理之后输出形式类似,key完全一样,其实key就表示结果矩阵中的第i行第k列,而reduce就是将<"M",j,Mij>和<"N",j,Njk>对应的元素相乘。
3)而map的输入形式是“1,1 87 ”(也就是i,j,Mij),而map的输出形式是(<i,k>,<"M",j,Mij>),只有k是未知的,其实k就是N的列数,也是结果矩阵的列数,
从M中读取的数据就只有i,j,Mij,k就是N的列数,所以:
if(filename.contains("M")){
String[] tuple=value.toString().split(",");
int i=Integer.parseInt(tuple[0]);
String[] tupleS=tuple[1].split("\t");
int j=Integer.parseInt(tupleS[0]);
int Mij=Integer.parseInt(tupleS[1]);
for (int k = 1; k <columnN+1 ; k++) {
map_key.set(i+","+k);
map_value.set("M"+","+j+","+Mij);
context.write(map_key, map_value);
}
}
从N矩阵中读取到j,k,Njk,所以i就是M的行数,对于N是:
else if(filename.contains("N")){
String[] tuple=value.toString().split(",");
int j=Integer.parseInt(tuple[0]);
String[] tupleS=tuple[1].split("\t");
int k=Integer.parseInt(tupleS[0]);
int Njk=Integer.parseInt(tupleS[1]);
for (int i = 1; i <rowM+1 ; i++) {
map_key.set(i+","+k);
map_value.set("N"+","+j+","+Njk);
context.write(map_key, map_value);
}
}
4)作业的配置,有个地方需要注意,就是设置了每个Map和Reduce节点都可以共享的三个变量:
conf.set("columnM", Integer.toString(columnM));
conf.set("rowM", Integer.toString(rowM));
conf.set("columnN", Integer.toString(columnN));
5)为了获得columnN和rowM,重载了Mapper的setup函数:
public void setup(Context context){
Configuration conf=context.getConfiguration();
columnN=Integer.parseInt(conf.get("columnN"));
rowM=Integer.parseInt(conf.get("rowM"));
}
通过conf的get函数获得。同样的,为获得columnM,也重载了Reducer的setup函数。
public void setup(Context context) throws IOException{
Configuration conf=context.getConfiguration();
columnM=Integer.parseInt(conf.get("columnM"));
}
6)由于定义的reduce数量是5,所以最终生成了5个结果文件。

MR实现--矩阵乘法的更多相关文章
- Codeforces 506E Mr. Kitayuta's Gift (矩阵乘法,动态规划)
描述: 给出一个单词,在单词中插入若干字符使其为回文串,求回文串的个数(|s|<=200,n<=10^9) 这道题超神奇,不可多得的一道好题 首先可以搞出一个dp[l][r][i]表示回文 ...
- Codeforces 506E - Mr. Kitayuta's Gift(神仙矩阵乘法)
Codeforces 题目传送门 & 洛谷题目传送门 神仙题 %%%%%%%%%%%%% u1s1 感觉这道题风格很省选( 下记 \(m=|s|\),首先探讨 \(n+m\) 为偶数的情形. ...
- ZOJ 2671 Cryptography 矩阵乘法+线段树
B - Cryptography Time Limit:5000MS Memory Limit:32768KB 64bit IO Format:%lld & %llu Subm ...
- *HDU2254 矩阵乘法
奥运 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submissi ...
- *HDU 1757 矩阵乘法
A Simple Math Problem Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Ot ...
- CH Round #30 摆花[矩阵乘法]
摆花 CH Round #30 - 清明欢乐赛 背景及描述 艺术馆门前将摆出许多花,一共有n个位置排成一排,每个位置可以摆花也可以不摆花.有些花如果摆在相邻的位置(隔着一个空的位置不算相邻),就不好看 ...
- POJ3070 Fibonacci[矩阵乘法]
Fibonacci Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 13677 Accepted: 9697 Descri ...
- bzoj 2738 矩阵乘法
其实这题跟矩阵乘法没有任何卵关系,直接整体二分,用二维树状数组维护(刚刚学会>_<),复杂度好像有点爆炸(好像有十几亿不知道是不是算错了),但我们不能怂啊23333. #include&l ...
- 【BZOJ-2476】战场的数目 矩阵乘法 + 递推
2476: 战场的数目 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 58 Solved: 38[Submit][Status][Discuss] D ...
随机推荐
- MFC 监控界面上所有文本框值的变化
//控件消息,菜单,按钮等 BOOL CXXDlg::OnCommand(WPARAM wParam, LPARAM lParam) { // TODO: 在此添加专用代码和/或调用基类 int wm ...
- Nim博弈(nim游戏)
http://blog.csdn.net/qiankun1993/article/details/6765688 NIM 游戏 重点结论:对于一个Nim游戏的局面(a1,a2,...,an),它是P- ...
- loj6087 毒瘤题
传送门:https://loj.ac/problem/6087 [题解] 这垃圾题目卡空间啊... k=1相信大家都会,把所有数异或起来就是答案了. 考虑k=2,把所有数异或起来得到两个答案数的异或值 ...
- bzoj 1001 平面图转对偶图 最短路求图最小割
原题传送门http://www.lydsy.com/JudgeOnline/problem.php?id=1001 整理了下之前A的题 平面图可以转化成对偶图,然后(NlogN)的可以求出图的最小割( ...
- 基于SSM框架web搜索功能的实现
这里适合选用于jsp搭建的网站,数据库采用MySQL 一.HTML <div class="header_search"> <input type="t ...
- kickstart构建Live CD 添加文件问题
在构建自定义ISO的时候,有时候需要从母体机器拷贝文件到Live CD系统.比如拷贝/home/xiaoxiaoleo/hello 程序,在Kickstart配置文件里, post脚本添加--noch ...
- LCD实验学习笔记(三):WATCH DOG
看门狗是为了能够防止程序跑飞用的.程序应该定时的去喂狗.如果程序跑飞了,那么就不会去喂狗了.如果超过了喂狗的时间,那么狗就会生成一个信号来reset CPU.一般程序不需要,特殊情况下需要这种机制. ...
- cdp协议通信并发编程基础之进程
一 . 基于UDP的套接字 udp是无链接的所以先启动哪一段都不会报错 udp服务端 import socket server=socket.socket(socket.AF_INET,socket. ...
- 自旋锁spin_lock和raw_spin_lock【转】
转自:http://blog.csdn.net/droidphone/article/details/7395983 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 临界区Cr ...
- appium===报错Failure [INSTALL_FAILED_ALREADY_EXISTS: Attempt to re-install io.appium.settings without first uninstalling.的解决办法
要解决的问题:appium在androidV7.0系统上运行时报错 Failure [INSTALL_FAILED_ALREADY_EXISTS: Attempt to re-install io.a ...