Die Berechnung der matrix-Determinante

Ich versuche, die Berechnung der Determinante einer matrix (beliebiger Größe), für selbst-Kodierung /interview Praxis. Mein Erster Versuch ist mit Rekursion und das führt mich zu folgender Umsetzung:

import java.util.Scanner.*;
public class Determinant {

    double A[][];
    double m[][];
    int N;
    int start;
    int last;

    public Determinant (double A[][], int N, int start, int last){
            this.A = A;
            this.N = N;
            this.start = start;
            this.last = last;
    }

    public double[][] generateSubArray (double A[][], int N, int j1){
            m = new double[N-1][];
            for (int k=0; k<(N-1); k++)
                    m[k] = new double[N-1];

            for (int i=1; i<N; i++){
                  int j2=0;
                  for (int j=0; j<N; j++){
                      if(j == j1)
                            continue;
                      m[i-1][j2] = A[i][j];
                      j2++;
                  }
              }
            return m;
    }
    /*
     * Calculate determinant recursively
     */
    public double determinant(double A[][], int N){
        double res;

        //Trivial 1x1 matrix
        if (N == 1) res = A[0][0];
        //Trivial 2x2 matrix
        else if (N == 2) res = A[0][0]*A[1][1] - A[1][0]*A[0][1];
        //NxN matrix
        else{
            res=0;
            for (int j1=0; j1<N; j1++){
                 m = generateSubArray (A, N, j1);
                 res += Math.pow(-1.0, 1.0+j1+1.0) * A[0][j1] * determinant(m, N-1);
            }
        }
        return res;
    }
}

So weit, es ist alles gut und es gibt mir ein richtiges Ergebnis. Nun würde ich gerne meinen code optimieren, indem Sie die Verwendung mehrerer threads für die Berechnung dieser Determinante Wert.
Ich habe versucht zu parallelisieren, es mit der Java Fork/Join-Modell. Dies ist mein Ansatz:

@Override
protected Double compute() {
     if (N < THRESHOLD) {
         result = computeDeterminant(A, N);
         return result;
     }

     for (int j1 = 0; j1 < N; j1++){
          m = generateSubArray (A, N, j1);
          ParallelDeterminants d = new ParallelDeterminants (m, N-1);
          d.fork();
          result += Math.pow(-1.0, 1.0+j1+1.0) * A[0][j1] * d.join();
     }

     return result;
}

public double computeDeterminant(double A[][], int N){
    double res;

    //Trivial 1x1 matrix
    if (N == 1) res = A[0][0];
    //Trivial 2x2 matrix
    else if (N == 2) res = A[0][0]*A[1][1] - A[1][0]*A[0][1];
    //NxN matrix
    else{
        res=0;
        for (int j1=0; j1<N; j1++){
             m = generateSubArray (A, N, j1);
             res += Math.pow(-1.0, 1.0+j1+1.0) * A[0][j1] * computeDeterminant(m, N-1);
        }
    }
    return res;
}

/*
 * Main function
 */
public static void main(String args[]){
    double res;
    ForkJoinPool pool = new ForkJoinPool();
    ParallelDeterminants d = new ParallelDeterminants();
    d.inputData();
    long starttime=System.nanoTime();
    res = pool.invoke (d);
    long EndTime=System.nanoTime();

    System.out.println("Seq Run = "+ (EndTime-starttime)/100000);
    System.out.println("the determinant valaue is  " + res);
}

Jedoch nach Vergleich der Leistung, fand ich, dass die Leistung des Fork/Join-Ansatz ist sehr schlecht, und je höher der matrix-dimension ist, desto langsamer wird es (im Vergleich zum ersten Ansatz). Wo ist der Aufwand? Kann jemand Aufschluss geben, wie das zu verbessern?

  • Vor dem Wurf in den threads, ich würd halt die Zuweisung in der Schleife. Eine Möglichkeit wäre, zwei array-Parameter, die bestimmen, welche Zeilen und Spalten zu berechnen, statt N.
  • Ich würde dir empfehlen, einen Blick auf einige algorithmen entwickelt, um parallel sein. Ich ging nicht durch den Algorithmus aber in meiner Erfahrung viele clevere Optimierungen finden für gemeinsame Probleme zu suchen um.
InformationsquelleAutor all_by_grace | 2013-05-17
Schreibe einen Kommentar