您的位置:首页 > 编程语言 > Java开发

基于内积法的Hadoop的MapReducer框架实现稀疏矩阵乘法(java)

2016-05-13 00:00 555 查看
摘要: 博主现在仅仅处于初研究阶段,若有错误望指正,不说其他的,直接给大家来点干货!

1、构建两个矩阵,此处写定,如下:

A={{1, 2, 3},{4, 5, 0},{7, 8, 9},{10, 11, 12}};

B={{13, 14},{0, 16},{17, 0}};

2、将矩阵转换成(row, col, value)形式存于文本中,其中row为行号,col为列号,同时只存储有效数据,即0不存储

private static void util(String fileName, int[][] arg){

try {

File file = new File(fileName);

if (!file.exists()) {

file.createNewFile();

}

System.out.println(arg[0].length + ", " + arg.length);

FileWriter fw = new FileWriter(file);

int i=0, j=0;

for (i = 0; i < arg.length; i++) {

for (j = 0; j < arg[0].length-1; j++) {

System.out.print(arg[i][j] + ", ");

if(arg[i][j]!=0){

fw.write((i+1)+" "+(j+1)+" "+arg[i][j]+"\n");

}

}

System.out.println(arg[i][j]);

if(arg[i][j]!=0){

fw.write((i+1)+" "+(j+1)+" "+arg[i][j]+"\n");

}

}

fw.close();

} catch (Exception e) {

e.printStackTrace();

}

}

private static void getATxt(){

util("matrixA.txt", A);

}

private static void getBTxt(){

util("matrixB.txt", B);

}

public static void main(String[] args) {

getATxt();

getBTxt();

}

3、生成的 matrixA.txt 和 matrixB.txt 结果及格式如下





4、在实现稀疏矩阵乘法之前,首先要了解MapReducer原理

在Map阶段,根据传入的文本数据,本次中为 m x j 的A矩阵和 j x n 的B矩阵通过A的行的每一位元素和B的列的对应每一位元素相乘的和,最后将得到一个 m x n 的C矩阵,故A的行或B的列作为outputValue,而Reducer阶段是根据outputKey相同自动将其分组形成一个list,故写入Reducer阶段的key应该相同,所以选择c的行号和列号,outputValue根据文件不同,区别是A的行还是B的列,故需加上标识。

在Reducer阶段,分割InputValue,根据标识不同,取出值并存入相应数据,最后实现对应位相乘然后相加得到c并输出到文件。

5、代码实现前推荐一个好方法,可以获取具体文件名,可根据文件名不同加上不同的标识

String pathName = ((FileSplit)context.getInputSplit()).getPath().toString();

6、具体代码实现

public class MatirxMult {

private static final int[][] A={{1, 2, 3},{4, 5, 0},{7, 8, 9},{10, 11, 12}};

private static final int[][] B={{13, 14},{0, 16},{17, 0}};

private static final int rowSizeA = A.length;//获取A的行数

private static final int colSizeA = A[0].length;//获取A的列数

private static final int colSizeB = B[0].length;//获取B的列数

private static class MatirxMultMapper extends Mapper<LongWritable, Text, Text, Text>{

private static int i=0;

@Override

protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, Text>.Context context)

throws IOException, InterruptedException {

//可以获取文件名,根据文件名来判定传入reducer的形式

String pathName = ((FileSplit)context.getInputSplit()).getPath().toString();

//strs[0]行值;strs[0]列值;strs[2]值

String[] strs = value.toString().split(" ");

if(pathName.contains("matrixA")){

for(i=0; i<colSizeB; i++){

context.write(new Text(strs[0]+":"+(i+1)), new Text(strs[1]+":"+strs[2]+":A"));

}

}else if(pathName.contains("matrixB")){

for(i=0; i<rowSizeA; i++){

context.write(new Text((i+1)+":"+strs[1]), new Text(strs[0]+":"+strs[2]+":B"));

}

}

}

}

private static class MatirxMultReducer extends Reducer<Text, Text, Text, IntWritable>{

@Override

protected void reduce(Text value, Iterable<Text> datas,

Reducer<Text, Text, Text, IntWritable>.Context context) throws IOException, InterruptedException {

String[] strsValue = value.toString().split(":");

int colA=0, rowB=0, valueA=0, valueB=0;

int[] vA = new int[colSizeA];//因为A对应行和B对应列必须为A的列数等于B的行数

int[] vB = new int[colSizeA];

for(Text data : datas){

String[] strs = data.toString().split(":");

if("A".equals(strs[2])){

colA = Integer.parseInt(strs[0]);

valueA = Integer.parseInt(strs[1]);

vA[colA-1] = valueA;//因为存文件的时候下标是从1开始,而数组下标从0开始,故需-1

}else if("B".equals(strs[2])){

rowB = Integer.parseInt(strs[0]);

valueB = Integer.parseInt(strs[1]);

vB[rowB-1] = valueB;

}

}

int result=0;

for(int j=0; j<colSizeA; j++){

result+=vA[j]*vB[j];

}

//C=AB, strsValue[0]为C的行号,strsValue[1]为C的列号,result位C的具体位置结果

context.write(new Text(strsValue[0]+":"+strsValue[1]), new IntWritable(result));

}

}

public static void main(String[] args) {

try {

Configuration cfg = HadoopCfg.getConfigration();

Job job = Job.getInstance(cfg);

job.setJobName("MatirxMult");

job.setJarByClass(MatirxMult.class);

job.setMapperClass(MatirxMultMapper.class);

job.setMapOutputKeyClass(Text.class);

job.setMapOutputValueClass(Text.class);

job.setReducerClass(MatirxMultReducer.class);

job.setOutputKeyClass(NullWritable.class);

job.setOutputValueClass(IntWritable.class);

FileInputFormat.addInputPath(job, new Path("/input/matrix"));

FileOutputFormat.setOutputPath(job, new Path("/MatirxMult/"));

System.exit(job.waitForCompletion(true) ? 0 : 1);

} catch (Exception e) {

e.printStackTrace();

}

}

}

7、结果展示(格式为:坐标,值)



写在最后:如有疑问可以提出,谢谢。博主是看了一篇论文,但是只取了其中一小部分实现。

论文名称:基于Hadoop的大矩阵乘法处理方法(孙远帅)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息