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实现--矩阵乘法的更多相关文章

  1. Codeforces 506E Mr. Kitayuta's Gift (矩阵乘法,动态规划)

    描述: 给出一个单词,在单词中插入若干字符使其为回文串,求回文串的个数(|s|<=200,n<=10^9) 这道题超神奇,不可多得的一道好题 首先可以搞出一个dp[l][r][i]表示回文 ...

  2. Codeforces 506E - Mr. Kitayuta's Gift(神仙矩阵乘法)

    Codeforces 题目传送门 & 洛谷题目传送门 神仙题 %%%%%%%%%%%%% u1s1 感觉这道题风格很省选( 下记 \(m=|s|\),首先探讨 \(n+m\) 为偶数的情形. ...

  3. ZOJ 2671 Cryptography 矩阵乘法+线段树

    B - Cryptography Time Limit:5000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Subm ...

  4. *HDU2254 矩阵乘法

    奥运 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submissi ...

  5. *HDU 1757 矩阵乘法

    A Simple Math Problem Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Ot ...

  6. CH Round #30 摆花[矩阵乘法]

    摆花 CH Round #30 - 清明欢乐赛 背景及描述 艺术馆门前将摆出许多花,一共有n个位置排成一排,每个位置可以摆花也可以不摆花.有些花如果摆在相邻的位置(隔着一个空的位置不算相邻),就不好看 ...

  7. POJ3070 Fibonacci[矩阵乘法]

    Fibonacci Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 13677   Accepted: 9697 Descri ...

  8. bzoj 2738 矩阵乘法

    其实这题跟矩阵乘法没有任何卵关系,直接整体二分,用二维树状数组维护(刚刚学会>_<),复杂度好像有点爆炸(好像有十几亿不知道是不是算错了),但我们不能怂啊23333. #include&l ...

  9. 【BZOJ-2476】战场的数目 矩阵乘法 + 递推

    2476: 战场的数目 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 58  Solved: 38[Submit][Status][Discuss] D ...

随机推荐

  1. 存储过程-----DECLARE---实用注意事项

    定义与使用变量时需要注意以下几点: ◆ DECLARE语句必须用在DEGIN…END语句块中,并且必须出现在DEGIN…END语句块的最前面,即出现在其他语句之前. ◆ DECLARE定义的变量的作用 ...

  2. JS中this的指向问题(读书笔记纯手打~)

    一.this JavaScrip的this总是指向一个对象,而具体指向哪个对象是在运行时基于函数的执行环境动态绑定的,而非函数被声明时的环境. 二.this的指向 根据运用情景可分为四类: 1.作为对 ...

  3. Sencha touch中Ext.List的使用及高度自适应

    最近在做 Sencha 的一个项目,需要用到 Ext.List 来列出所需商品及相关信息,平时我们使用 Ext.List 都是使用  fullscreen:true  来设置 List 全屏显示, 但 ...

  4. tomcat:tomcat的OutOfMemoryError解决

    最近在熟悉一个开发了有几年的项目,需要把数据库从mysql移植到oracle,首先把jdbc的连接指向 mysql,打包放到tomcat里面,可以跑起来,没有问题,可是当把jdbc连接指向oracle ...

  5. 【BZOJ2039】【2009国家集训队】人员雇佣 [最小割]

    人员雇佣 Time Limit: 20 Sec  Memory Limit: 259 MB[Submit][Status][Discuss] Description 作为一个富有经营头脑的富翁,小L决 ...

  6. 【BZOJ】1708: [Usaco2007 Oct]Money奶牛的硬币

    [算法]DP [题解] 如果每个排列算一种,则令f[i]表示凑成面值为i的方案数,容易推出f[i]+=f[i-a[j]]. 现在是每个组合才算一种,令f[i][j]第二维表示只使用前j种面值,f[i] ...

  7. 【洛谷 P3805】 【模板】manacher算法

    题目链接 manacher算法:在线性时间内求一个字符串中所有/最长回文串的算法. 先来考虑一下暴力的算法,枚举每个中点,向两边扩展,时间复杂度\(O(n^2)\). 来分析下此算法的缺点. 1.因为 ...

  8. Sequence(ST表)(洛谷P2048)

    超级钢琴 知识储备 在做这道题前,我们先要了解一下ST表(一种离线求区间最值的方法) ST表使用DP实现的,其查询复杂度为O(1). 那么我们怎么用DP实现呢?? 首先,我们设立一个状态f[i][j] ...

  9. bzoj 1089 SCOI2003严格n元树 递推

    挺好想的,就是一直没调过,我也不知道哪儿的错,对拍也拍了,因为数据范围小,都快手动对拍了也不知道 哪儿错了.... 我们定义w[i]代表深度<=i的严格n元树的个数 那么最后w[d]-w[d-1 ...

  10. Linux rar乱码

    大家都知道,Linux下的中文乱码是一个很烦的事情,在这里我叫大家如何解决这个问题. rar乱码 ubunut下打开rar包,如果里面有中文就会显示乱码,其实就觉这个问题最简单了,只要把进入新立得,搜 ...