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 ...
随机推荐
- 阻塞DOM
DOM是解析后的HTML. 这些阻塞因素我们可以叫做 阻塞渲染的资源 ,例如 HTML.CSS(也包括web font)和 JavaScript. 请注意,图像是不会阻塞渲染的 ,所以如果有图像落在蓝 ...
- javascript批量输入表单
void((function(){ x=document.getElementsByTagName("a"); y = x[1] y.click() })()) void((fun ...
- eclipse断点调试时不能进入断点调试
页面JavaScript代码有错误!!!F12调试.
- springmvc JSR303 Validate 注解式,校验数据
参考:http://www.cnblogs.com/liukemng/category/578644.html 先进行配置: <!-- 默认的注解映射的支持 --> <mvc:ann ...
- IOS UITableViewUITableView小技巧--实现cell向左滑动删除,编辑等功能
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { return Y ...
- .NET DataSet DataTable 导出excel
public void CreateExcel(DataSet ds, string FileName) { HttpResponse resp; resp = Page.Response; resp ...
- request.getRequestDispatcher(url).forward(request, response)
request.getRequestDispatcher().forward(request, response) 意思是将客户端的请求转向到 getRequestDispatcher()方法中参数定 ...
- docker从零开始(一)centos获取安装docker-ce
卸载旧版本 较旧版本的Docker被称为docker或docker-engine.如果已安装这些,请卸载它们以及相关的依赖项. centos7 yum安装的docker就是docker-engine ...
- ros 如何使用 openni2_launch
There is very little actual code/etc in openni2_launch, it is mostly a thin wrapper around openni2_c ...
- mySQL的存储过程详解
mysql存储过程详解 1. 存储过程简介 我们常用的操作数据库语言SQL语句在执行的时候需要要先编译,然后执行,而存储过程(Stored Procedure)是一组为了完成特定功能的S ...