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. 阻塞DOM

    DOM是解析后的HTML. 这些阻塞因素我们可以叫做 阻塞渲染的资源 ,例如 HTML.CSS(也包括web font)和 JavaScript. 请注意,图像是不会阻塞渲染的 ,所以如果有图像落在蓝 ...

  2. javascript批量输入表单

    void((function(){ x=document.getElementsByTagName("a"); y = x[1] y.click() })()) void((fun ...

  3. eclipse断点调试时不能进入断点调试

    页面JavaScript代码有错误!!!F12调试.

  4. springmvc JSR303 Validate 注解式,校验数据

    参考:http://www.cnblogs.com/liukemng/category/578644.html 先进行配置: <!-- 默认的注解映射的支持 --> <mvc:ann ...

  5. IOS UITableViewUITableView小技巧--实现cell向左滑动删除,编辑等功能

    - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { return Y ...

  6. .NET DataSet DataTable 导出excel

    public void CreateExcel(DataSet ds, string FileName) { HttpResponse resp; resp = Page.Response; resp ...

  7. request.getRequestDispatcher(url).forward(request, response)

    request.getRequestDispatcher().forward(request, response) 意思是将客户端的请求转向到 getRequestDispatcher()方法中参数定 ...

  8. docker从零开始(一)centos获取安装docker-ce

    卸载旧版本 较旧版本的Docker被称为docker或docker-engine.如果已安装这些,请卸载它们以及相关的依赖项. centos7 yum安装的docker就是docker-engine ...

  9. ros 如何使用 openni2_launch

    There is very little actual code/etc in openni2_launch, it is mostly a thin wrapper around openni2_c ...

  10. mySQL的存储过程详解

    mysql存储过程详解 1.      存储过程简介   我们常用的操作数据库语言SQL语句在执行的时候需要要先编译,然后执行,而存储过程(Stored Procedure)是一组为了完成特定功能的S ...