2012-03-14 49 views
5

Tôi đang chạy chương trình Phép nhân ma trận MapReduce được tìm thấy tại http://www.norstad.org/matrix-multiply/index.html. Tôi phát hiện ra rằng triển khai này không hoạt động đúng khi có 0 trong ma trận đầu vào. Nhưng tôi không hiểu tại sao, và làm thế nào để tôi sửa đổi chương trình để làm cho nó hoạt động? Các hoạt động MapReduce hoàn tất, nhưng sản lượng luôn luôn là một ma trận với tất cả các yếu tố 0.Nhân bản ma trận Hadoop

đầu vào My ma trận A & B là:

Matrix A  Matrix B 
0 0 0  6 7 4 
0 1 6  9 1 3 
7 8 9  7 6 2 

Output Matrix:

0 0 0 
0 0 0 
0 0 0 

Sau đây là được lấy từ tệp nhật ký cho công việc:

Đầu ra bản đồ cho ma trậnB:

##### Map setup: matrixA = false for hdfs://localhost/user/hadoop-user/B 
strategy = 4 
R1 = 4 
I = 3 
K = 3 
J = 3 
IB = 3 
KB = 3 
JB = 3 
##### Map input: (0,0) 6 
##### Map output: (0,0,0,1) (0,0,6) 
##### Map input: (0,1) 7 
##### Map output: (0,0,0,1) (0,1,7) 
##### Map input: (0,2) 4 
##### Map output: (0,0,0,1) (0,2,4) 
##### Map input: (1,0) 9 
##### Map output: (0,0,0,1) (1,0,9) 
##### Map input: (1,1) 1 
##### Map output: (0,0,0,1) (1,1,1) 
##### Map input: (1,2) 3 
##### Map output: (0,0,0,1) (1,2,3) 
##### Map input: (2,0) 7 
##### Map output: (0,0,0,1) (2,0,7) 
##### Map input: (2,1) 6 
##### Map output: (0,0,0,1) (2,1,6) 
##### Map input: (2,2) 2 
##### Map output: (0,0,0,1) (2,2,2) 

Bản đồ đầu ra cho Matrix A:

##### Map setup: matrixA = true for hdfs://localhost/user/hadoop-user/A 
strategy = 4 
R1 = 4 
I = 3 
K = 3 
J = 3 
IB = 3 
KB = 3 
JB = 3 
##### Map input: (1,1) 1 
##### Map output: (0,0,0,0) (1,1,1) 
##### Map input: (1,2) 6 
##### Map output: (0,0,0,0) (1,2,6) 
##### Map input: (2,0) 7 
##### Map output: (0,0,0,0) (2,0,7) 
##### Map input: (2,1) 8 
##### Map output: (0,0,0,0) (2,1,8) 
##### Map input: (2,2) 9 
##### Map output: (0,0,0,0) (2,2,9) 

ý rằng bản đồ cho ma trận A không đọc số không từ tập tin đầu vào. Lưu ý: cả hai tệp đầu vào đều được lưu trữ trong HDFS dưới dạng tệp trình tự và đầu ra cũng là một tệp chuỗi. Ai đó có thể làm sáng tỏ vấn đề là gì không? Cảm ơn!

Mã cho lớp Mapper được đưa ra dưới đây:

/** The job 1 mapper class. */ 

private static class Job1Mapper 
    extends Mapper<IndexPair, IntWritable, Key, Value> 
{ 
    private Path path; 
    private boolean matrixA; 
    private Key key = new Key(); 
    private Value value = new Value(); 

    public void setup (Context context) { 
     init(context); 
     FileSplit split = (FileSplit)context.getInputSplit(); 
     path = split.getPath(); 
     matrixA = path.toString().startsWith(inputPathA); 
     if (DEBUG) { 
      System.out.println("##### Map setup: matrixA = " + matrixA + " for " + path); 
      System.out.println(" strategy = " + strategy); 
      System.out.println(" R1 = " + R1); 
      System.out.println(" I = " + I); 
      System.out.println(" K = " + K); 
      System.out.println(" J = " + J); 
      System.out.println(" IB = " + IB); 
      System.out.println(" KB = " + KB); 
      System.out.println(" JB = " + JB); 
     } 
    } 

    private void printMapInput (IndexPair indexPair, IntWritable el) { 
     System.out.println("##### Map input: (" + indexPair.index1 + "," + 
      indexPair.index2 + ") " + el.get()); 
    } 

    private void printMapOutput (Key key, Value value) { 
     System.out.println("##### Map output: (" + key.index1 + "," + 
      key.index2 + "," + key.index3 + "," + key.m + ") (" + 
      value.index1 + "," + value.index2 + "," + value.v + ") "); 
    } 

    private void badIndex (int index, int dim, String msg) { 
     System.err.println("Invalid " + msg + " in " + path + ": " + index + " " + dim); 
     System.exit(1); 
    } 

    public void map (IndexPair indexPair, IntWritable el, Context context) 
     throws IOException, InterruptedException 
    { 
     if (DEBUG) printMapInput(indexPair, el); 
     int i = 0; 
     int k = 0; 
     int j = 0; 
     if (matrixA) { 
      i = indexPair.index1; 
      if (i < 0 || i >= I) badIndex(i, I, "A row index"); 
      k = indexPair.index2; 
      if (k < 0 || k >= K) badIndex(k, K, "A column index"); 
     } else { 
      k = indexPair.index1; 
      if (k < 0 || k >= K) badIndex(k, K, "B row index"); 
      j = indexPair.index2; 
      if (j < 0 || j >= J) badIndex(j, J, "B column index"); 
     } 
     value.v = el.get(); 
       if (matrixA) { 
        key.index1 = i/IB; 
        key.index3 = k/KB; 
        key.m = 0; 
        value.index1 = i % IB; 
        value.index2 = k % KB; 
        for (int jb = 0; jb < NJB; jb++) { 
         key.index2 = jb; 
         context.write(key, value); 
         if (DEBUG) printMapOutput(key, value); 
        } 
       } else { 
        key.index2 = j/JB; 
        key.index3 = k/KB; 
        key.m = 1; 
        value.index1 = k % KB; 
        value.index2 = j % JB; 
        for (int ib = 0; ib < NIB; ib++) { 
         key.index1 = ib; 
         context.write(key, value); 
         if (DEBUG) printMapOutput(key, value); 
        } 
     } 
    } 
} 

Nếu có bất kỳ lỗi cú pháp, nó chỉ vì tôi copy-dán mã và sửa đổi nó ở đây, vì vậy tôi có thể đã bỏ qua điều gì đó.

Tôi cần trợ giúp về logic của hàm Bản đồ, không đọc 0 từ tệp đầu vào, bất kỳ ai cũng có thể cho tôi biết lý do không?

+1

Đây là hơn 700 dòng mã. Bạn có nghĩ rằng bất cứ ai sẽ gỡ lỗi thông qua điều này cho bạn? –

+0

Tôi đã sửa đổi bài đăng của mình để chỉ bao gồm mã lớp bản đồ. Tôi cần trợ giúp về logic, theo nghĩa nào đó, tôi không thể đưa ra giải thích là tại sao 0 không được đọc bởi tệp đầu vào bởi hàm Bản đồ. – Chaos

+0

@ThomasJungblut - Tôi nghĩ bạn sẽ quảng bá Hama cho phép nhân Matrix :) –

Trả lời

3

Trong TestMatrixMultiply.java, từ trang web bạn liên kết, mà có lẽ chứa mã bạn đang sử dụng để mã hóa ma trận của bạn sang định dạng tập tin IndexPair hậu thuẫn dự kiến, có chức năng writeMatrix:

public static void writeMatrix (int[][] matrix, int rowDim, int colDim, String pathStr) 
    throws IOException 
{ 
    Path path = new Path(pathStr); 
    SequenceFile.Writer writer = SequenceFile.createWriter(fs, conf, path, 
     MatrixMultiply.IndexPair.class, IntWritable.class, 
     SequenceFile.CompressionType.NONE); 
    MatrixMultiply.IndexPair indexPair = new MatrixMultiply.IndexPair(); 
    IntWritable el = new IntWritable(); 
    for (int i = 0; i < rowDim; i++) { 
     for (int j = 0; j < colDim; j++) { 
      int v = matrix[i][j]; 
      if (v != 0) { // !!! well, that would be why we aren't writing 0s 
       indexPair.index1 = i; 
       indexPair.index2 = j; 
       el.set(v); 
       writer.append(indexPair, el); 
      } 
     } 
    } 
    writer.close(); 
} 

Nhận xét được chèn vào dòng thứ hai của vòng lặp bên trong for.

Trình ánh xạ của bạn đang đọc không có 0 vì tệp nhập của bạn không chứa 0.

Mã được thiết kế nặng để giả định rằng tất cả các giá trị bị thiếu là 0 và nó thực hiện các kiểm tra bổ sung để tránh phát ra 0 giây, để cố gắng giảm thiểu lưu lượng mạng.

Tất cả mọi thứ dưới đây chủ yếu là sai vì tôi hiểu lầm thuật toán
(phần trên vẫn còn hữu ích, mặc dù)

Từ trang liên kết, bạn đang sử dụng chiến lược 3. Chiến lược 3 dựa về hành vi phân vùng và thứ tự sắp xếp. Thật không may, phân vùng là sai! Điều này tách biệt với số 0 không được in ra. Trình phân vùng chỉ vừa sai ở đây và bạn sẽ nhận được các ma trận đầy 0s vì nó nhân với dữ liệu đã được khởi tạo trước đó thành 0 và không bao giờ ghi đè dữ liệu chính xác cho khối đó.Điều này được ẩn trên thao tác 1 máy, bởi vì trình phân vùng là một phép toán rỗng, nhưng bị ngắt trong hầu hết các cụm.

Các phân vùng bản đồ chính trung gian (kb, jb, ib) vào một r giảm như sau:

r = (jb*KB + kb) mod R

Nó cần phải đảm bảo rằng tất cả các phím cho cùng một khối được phân công cùng một bộ giảm tốc. Thật không may, nó đảm bảo rằng điều này sẽ không xảy ra trừ khi KB % numReducers == 0:

map (key, value) 
    if from matrix A with key=(i,k) and value=a(i,k) 
     for 0 <= jb < NJB 
     emit (k/KB, jb, i/IB), (i mod IB, k mod KB, a(k,j)) // compare this... 
    if from matrix B with key=(k,j) and value=b(k,j) 
     emit (k/KB, j/JB, -1), (k mod KB, j mod KB, b(k,j)) // ...to this 

Đối với ma trận A, jb chủ chốt đang được lặp. Đối với ma trận B, jb chính đang được tính toán. Vì gán cho bộ giảm tốc là vòng tròn, điều này đảm bảo rằng các khóa A-matrix sẽ không được gán cho cùng một bộ giảm tốc như các khóa B-matrix. Do đó, thuật toán thất bại, vì nó giả định một cái gì đó về gán và sắp xếp các khóa được chứng minh là không chính xác. Đó là chính xác về thứ tự chính nếu và chỉ khi có một bộ giảm tốc mà tất cả các khóa được gán, nhưng trình phân vùng là sai!

Trình phân vùng phải được sửa đổi để sử dụng kb % numReducers cho Chiến lược 3. Đây không phải là trình phân vùng rất tốt, nhưng nó là trình phân vùng duy nhất hoạt động vì các khóa không giống nhau được yêu cầu sắp xếp đến cùng một trình giảm tốc trong một gọi món.

Mã mà bạn thực sự đưa vào bên trong câu hỏi không liên quan đến nơi lỗi thực sự tồn tại.

+0

cảm ơn bạn rất nhiều vì đã trả lời. Tôi sẽ đi đến phòng thí nghiệm vào ngày mai, và kiểm tra xem điều này có hiệu quả không, và tôi sẽ cho bạn biết :) – Chaos

+1

@shailesh, đừng dành quá nhiều thời gian cho nó - tôi vừa mới nhận ra rằng tôi sai. Các tham số chính là theo khối, và các khối A-ma trận cần phải được gán cho mỗi khối ma trận B tương ứng, vì vậy việc lặp lại là thích hợp; đó là một mối quan hệ 1: 1, không phải là một mối quan hệ phạm vi. Bây giờ tôi nghi ngờ điều này có liên quan nhiều hơn đến việc khởi tạo hàng bị bỏ qua do không có một khối ở vị trí mong đợi, nhưng tôi sẽ phải thử lại. Câu trả lời của tôi về phân vùng là sai, mặc dù 0-phát hiện là viết tắt. Hãy thử xóa kiểm tra khác 0 và tìm hiểu điều gì sẽ xảy ra? –

+0

có bạn đã đúng về việc kiểm tra không bằng không, tôi đã xóa nó và nó hoạt động tốt! Tôi không thể tin rằng tôi đã bỏ qua một lỗi đơn giản như vậy! Cảm ơn rất nhiều vì đã chỉ ra nó :). – Chaos

Các vấn đề liên quan