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. oralce的客户端sqlplus

    安装完oracle后,默认的客户端是sqlplus,还有一个公司常用的是PLSQLdeveloper 客户端软件,另外Navicat primie这个可以连接mysql.sqlserver.oracl ...

  2. ntpq –p命令

    ntpq用来监视ntpd操作,ntpq -p查询网络中的NTP服务器,同时显示客户端和每个服务器的关系 [root@ ~]# ntpq -p remote refid st t when poll r ...

  3. 线程 ManualResetEvent 类

    Reset(): 当一个线程开始一个活动(此活动必须完成后,其他线程才能开始)时, 它调用 Reset 以将 ManualResetEvent 置于非终止状态.此线程可被视为控制 ManualRese ...

  4. event对象和事件冒泡

    <!DOCTYPE HTML><html><head> <meta charset="utf-8"> <title>无标 ...

  5. Java拷贝构造函数初尝试

    浅复制(浅克隆) :被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象. 深复制(深克隆) :被复制 ...

  6. c#之字符串函数

    1.常用的字符串函数 Compare 比较字符串的内容,考虑文化背景(场所),确定某些字符是否相等 int Compare(string str1,string str2) int Compare(s ...

  7. 关于flume的几道题

    1,要求:监听一个tcp,udp端口41414将数据打印在控制台 # example.conf: A single-node Flume configuration # Name the compon ...

  8. WIN8.1优化

    用WIN8.1至今,总结的所有优化的办法! 从Win7.Win8.1开始,微软为我们带来完善的系统服务.任务计划程序,这些都一定程度提升了日常使用,实现了“半自动化.半智能化”交互体验.但是对于高级用 ...

  9. 微信支付http://www.cnblogs.com/True_to_me/p/3565039.html

    公众号支付有2种支付方式: JS API 支付:是指用户打开图文消息或者扫描二维码,在微信内置浏览器打开网页进行的支付.商户网页前端通过使用微信提供的 JS API,调用微信支付模块.这种方式,适合需 ...

  10. happens-before规则

    happens-before原则: happens-before它是判断数据是否存在竞争.线程是否安全的主要依据.为了保证线程安全我们可以让2个操作具有happens-before关系.(JDK5 开 ...