这期内容当中小编将会给大家带来有关mapreduce中怎么实现矩阵相乘,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。
设,
,那么
矩阵乘法要求左矩阵的列数与右矩阵
的行数相等,
的矩阵
,与
的矩阵
相乘,结果为
的矩阵
。
现在我们来分析一下,哪些操作是相互独立的(从而可以进行分布式计算)。很显然,的计算和
的计算是互不干扰的;事实上,
中各个元素的计算都是相互独立的。这样,我们在Map阶段,可以把计算
所需要的元素都集中到同一个key中,然后,在Reduce阶段就可以从中解析出各个元素来计算
;
的其他元素的计算同理。
我们还需要注意,会被
、
……
的计算所使用,
会被
、
……
的计算所使用。也就是说,在Map阶段,当我们从HDFS取出一行记录时,如果该记录是
的元素,则需要存储成
个<key, value>对,并且这
个key互不相同;如果该记录是
的元素,则需要存储成
个<key, value>对,同样的,
个key也应互不相同;但同时,用于计算
的、存放
、
……
和
、
……
的<key, value>对的key应该都是相同的,这样才能被传递到同一个Reduce中。
经过以上分析,整个计算过程设计为:
(1)在Map阶段,把来自表的元素
,标识成
条<key, value>的形式。其中
,
;把来自表
的元素
,标识成
条<key, value>形式,其中
,
。
于是乎,在Map阶段,我们实现了这样的战术目的:通过key,我们把参与计算的数据归为一类。通过value,我们能区分元素是来自
还是
,以及具体的位置。
(2)在Shuffle阶段,相同key的value会被加入到同一个列表中,形成<key, list(value)>对,传递给Reduce,这个由Hadoop自动完成。
(3)在Reduce阶段,有两个问题需要自己问问:
当前的<key, list(value)>对是为了计算的哪个元素?
list中的每个value是来自表或表
的哪个位置?
第一个问题可以从key中获知,因为我们在Map阶段已经将key构造为形式。第二个问题,也可以在value中直接读出,因为我们也在Map阶段做了标志。
接下来我们所要做的,就是把list(value)解析出来,来自的元素,单独放在一个数组中,来自
的元素,放在另一个数组中,然后,我们计算两个数组(各自看成一个向量)的点积,即可算出
的值。
示例矩阵和
相乘的计算过程如下图所示:
其中map阶段:
public static class MatrixMap extends Mapper<Object, Text, Text, Text>{
private int sum3 = 0; //存放矩阵a的行数
private int sum4 = 0; //存放矩阵b的行数
@Override
protected void map(Object key, Text value, Context context)
throws IOException, InterruptedException {
String[] lines = value.toString().split(",");
String url = ((FileSplit)context.getInputSplit()).getPath().toString();
//取出文件路径名,判断数据来源分别增加其行数
if(url.contains("matrix3")) sum3++;
if(url.contains("matrix4")) sum4++;
for(int m = 0; m < lines.length; m++){
// 遍历矩阵列数,分别与行数组成key为(i,k),value为(a,j,v)的数据输出
if(url.contains("matrix3") && lines.length == matrix_j){
for (int i = 1; i <= matrix_k; i++){
context.write(new Text(sum3+","+i),
new Text("a,"+(m+1)+","+lines[m]));
}
}else if(url.contains("matrix4") && lines.length == matrix_k){
for (int i = 1; i <= matrix_i; i++){
context.write(new Text(i+","+(m+1)),
new Text("b,"+sum4+","+lines[m]));
}
}
}
}
}
reduce阶段:
public static class MatrixReduce extends Reducer<Text, Text, Text, Text>{
private Map<Integer, Integer> matrix_a;
private Map<Integer, Integer> matrix_b;
@Override
protected void reduce(Text key, Iterable<Text> values, Context context)
throws IOException, InterruptedException {
matrix_a = new HashMap<Integer, Integer>();
matrix_b = new HashMap<Integer, Integer>();
for(Text value : values){
//循环分辨values中值是矩阵a或是b的,并存入map集合a和b中
String line = value.toString();
if(line.startsWith("a,")){
String[] lines = line.split(",");
if(lines.length == 3)
matrix_a.put(Integer.parseInt(lines[1]),
Integer.parseInt(lines[2]));
}else{
String[] lines = line.split(",");
if(lines.length == 3)
matrix_b.put(Integer.parseInt(lines[1]),
Integer.parseInt(lines[2]));
}
}
int a_value = 0;
int b_value = 0;
int result = 0;
//分别取出a和b集合中,计算结果放入result中
for(int i = 1; i <= matrix_j; i++){
if(matrix_a.get(i) != null && matrix_b.get(i) != null){
a_value = matrix_a.get(i);
b_value = matrix_b.get(i);
result += a_value * b_value;
}
}
context.write(key, new Text(result+""));
}
}
主程序:
public static void run(String time, Configuration conf)
throws IOException, ClassNotFoundException, InterruptedException{
// 需求输出文件路径
String outpath = VALUE_FSNAME+
"/data/test_out/zk/matrix-"+time;
// 需求输入文件路径
String input1 = VALUE_FSNAME+"/data/test_in/matrix3";
String input2 = VALUE_FSNAME+"/data/test_in/matrix4";
File jarFile = EJob.createTempJar("bin");
@SuppressWarnings("deprecation")
Job job = new Job(conf, "Test-Matrix");
job.setJarByClass(TestMatrix1.class);
job.setMapperClass(MatrixMap.class);
job.setReducerClass(MatrixReduce.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(Text.class);
job.setNumReduceTasks(1);
job.setInputFormatClass(TextInputFormat.class);
job.setOutputFormatClass(TextOutputFormat.class);
FileInputFormat.addInputPaths(job, input1+","+input2);;
FileOutputFormat.setOutputPath(job, new Path(outpath));
// 提交job
if (job.waitForCompletion(true)) {
System.err.println("计算完成!");
} else {
System.err.println("error!请检查程序!");
}
}
最后,大家请看一下原始数据:
matrix1:
1,2,3 4,5,0 7,8,9 10,11,12
matrix2:
10,15 0,2 11,9
上述就是小编为大家分享的mapreduce中怎么实现矩阵相乘了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注亿速云行业资讯频道。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。
原文链接:https://my.oschina.net/ssrs2202/blog/494516