【问题标题】:How to transpose a matrix in java (parallel/multithreaded)如何在java中转置矩阵(并行/多线程)
【发布时间】:2018-03-01 21:59:59
【问题描述】:

我们都知道矩阵转置有多大用处,写一个通用的算法供顺序使用是没问题的。但是,我在为多线程目的做同样的事情时遇到了一些麻烦,并且只有这个 4 x 4 的小机箱才能正常工作。

我的方法是将 double[][] 结构的相等部分(在本例中为 2 x 2)分配给四个线程中的每一个。在这种情况下,这意味着起始位置为 0,0 & 0,2 & 2,0 & 2,2。这是通过“kol”和“rad”传入的。

但是,我不能让它在更大的矩阵上工作,所以任何帮助都将不胜感激。我发现这个问题最接近的答案是:How to to parallelize the matrix transpose?

这也是我将 double[][] 结构拆分为四部分的灵感。我的(工作)4 x 4 代码可以在下面找到,那么如何修改它以适用于四个线程?

干杯!

public double[][] transponerMatrise(double[][] matrise, int rad, int 
kol, int id)
{
  if((id != 2))
   {
      for (int i = rad; i < n/2 + rad; i++)
      {
        for (int j = kol+1; j < n/2 + kol; j++)
        {
          System.out.println("Traad " + id + " bytter " + i + "," + j + " med " + j + "," + i);
          System.out.println("Value is " + matrise[i][j] + ", " + matrise[j][i]);
            element = matrise[i][j];
            matrise[i][j] = matrise[j][i];
            matrise[j][i] = element;
        }
      }
    }
    else
    {
      for (int i = rad; i < n/2 + rad-1; i++)
      {
        for (int j = kol; j < n/2 + kol; j++)
        {
          System.out.println("Traad " + id + " bytter " + i + "," + j + " med " + j + "," + i);
          System.out.println("Value is " + matrise[i][j] + ", " + matrise[j][i]);
            element = matrise[i][j];
            matrise[i][j] = matrise[j][i];
            matrise[j][i] = element;
        }
      }
    }
    return matrise;
}

PS:我知道代码可以正常工作,因为我有一个针对工作顺序变体的检查方法。

【问题讨论】:

    标签: java multithreading matrix parallel-processing transpose


    【解决方案1】:

    这是与 O(N^2) 成本函数的先验失败的斗争

    如果我可以将您的注意力转向更聪明的方法,成本几乎为O(1)(恒定),那么这个技巧将帮助您开始朝着更有希望的方向工作。

    可以尝试在矩阵元素的高性能调整(缓存线友好的“原始”存储)之上添加一个薄抽象层。这个抽象层将有助于访问“原始”存储(使用索引轴,索引跨步和切片技巧 - 与 HPC FORTRAN 库启发著名的 numpy 和它的跨步技巧的方式非常相似)和这种方式 .T-method 不会做任何昂贵的事情(就像推土机 N^2 内存位置,在那里和回来交换),而只是在抽象层交换轴参数,负责间接映射器,需要几十个纳秒对于任何大的 matrise[N,N]; where N = 10, 100, 1000, 10000, 100000, 1000000, 10000000+ 仍然是 一些 [ns]

    在执行此操作或其他更复杂的矩阵运算时没有比这更快的了,FORTRAN 和 numpy,性能优化,方法本身就是这种观察的证明。

    【讨论】:

      【解决方案2】:

      也许使用线程将行交换为 col 可能是一个简单的想法,但因此您需要两倍的内存来存储矩阵,这在大型矩阵上可能是个问题。另外,如果您有 6 核 CPU,我认为使用 100 个线程并没有太多好处,因此我的线程池非常小。正如@user3666197 提到的那样,它仍然是一个昂贵的解决方案-但并行;-)

      import java.util.concurrent.CountDownLatch;
      import java.util.concurrent.ExecutorService;
      import java.util.concurrent.Executors;
      
      public class MatrixTransposition {
      
          public static void main(final String[] args) throws InterruptedException {
              final MatrixTransposition transposition = new MatrixTransposition();
              final int[][] source = transposition.create(32);
              final int[][] transposed = transposition.solve(source);
              System.out.println("Compare source and transpositon = " + transposition.compare(source, transposed));
              final int[][] result = transposition.solve(transposed);
              System.out.println("Compare source and double transpositon = " + transposition.compare(source, result));
      
              transposition.print(source);
              transposition.print(transposed);
          }
      
          public boolean compare(final int[][] a, final int[][] b) {
              for (int r = 0; r < a.length; r++) {
                  for (int c = 0; c < a[0].length; c++) {
                      if (a[r][c] != b[r][c]) return false;
                  }
              }
              return true;
          }
      
          public int[][] create(final int size) {
              final int[][] result = new int[size][size];
              for (int r = 0; r < size; r++) {
                  for (int c = 0; c < size; c++) {
                      result[r][c] = r * size + c;
                  }
              }
              return result;
          }
      
          public void print(final int[][] input) {
              final int size = input.length;
              final int maxNr = size * size;
              final int digits = new String(maxNr + "").length();
              final String cellFormat = "%0" + digits + "d ";
      
              for (int r = 0; r < input.length; r++) {
                  final int[] row = input[r];
                  for (final int c : row) {
                      System.out.print(String.format(cellFormat, c));
                  }
                  System.out.println("");
              }
      
              System.out.println("");
          }
      
          public int[][] solve(final int[][] input) throws InterruptedException {
              final int width = input.length;
              final int height = input[0].length;
      
              final int[][] result = new int[width][height];
              final CountDownLatch latch = new CountDownLatch(width);
              for (int r = 0; r < width; r++) {
                  final int row = r;
                  threadPool.execute(() -> {
                      solvePart(result, input, row);
                      latch.countDown();
                  });
              }
      
              latch.await();
              return result;
          }
      
          private void solvePart(final int[][] result, final int[][] input, final int r) {
              System.out.println("Solve row " + String.format("%02d", r) + " in thread " + Thread.currentThread().getName());
              final int[] row = input[r];
              for (int c = 0; c < row.length; c++) {
                  result[c][r] = row[c];
              }
          }
          private final ExecutorService threadPool = Executors.newFixedThreadPool(6);
      }
      

      【讨论】:

        【解决方案3】:

        基于 user3666197 的方法,您可以这样做:

        public class Matrix {
        
                private class Index {
                    Index(final int row, final int col) {
                        super();
                        this.row = row;
                        this.col = col;
                    }
        
                    int col;
                    int row;
                }
        
                public Matrix(final int rows, final int cols) {
                    this.rows = rows;
                    this.cols = cols;
                    data = new int[rows][cols];
                }
        
                public int get(final int row, final int col) {
                    return get(getIndex(row, col));
                }
        
                public void set(final int row, final int col, final int value) {
                    set(getIndex(row, col), value);
                }
        
                public void transpose() {
                    transpositioned = !transpositioned;
                }
        
                private int get(final Index index) {
                    return data[index.row][index.col];
                }
        
                private Index getIndex(final int row, final int col) {
                    return transpositioned ? new Index(col, row) : new Index(row, col);
                }
        
                private void set(final Index index, final int value) {
                    data[index.row][index.col] = value;
                }
        
                private final int cols;
                private final int[][] data;
                private final int rows;
                private boolean transpositioned;
        
            }
        

        【讨论】:

          猜你喜欢
          • 2013-05-27
          • 2018-07-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-09-23
          • 2011-05-15
          • 2017-05-04
          相关资源
          最近更新 更多