public void Dsymv(Boolean isUpperTriangular, double alpha, DoubleMatrix2D A, DoubleMatrix1D x, double beta, DoubleMatrix1D y) { if (isUpperTriangular) { A = A.ViewDice(); } Property.DEFAULT.CheckSquare(A); int size = A.Rows; if (size != x.Size || size != y.Size) { throw new ArgumentException(A.ToStringShort() + ", " + x.ToStringShort() + ", " + y.ToStringShort()); } DoubleMatrix1D tmp = x.Like(); for (int i = 0; i < size; i++) { double sum = 0; for (int j = 0; j <= i; j++) { sum += A[i, j] * x[j]; } for (int j = i + 1; j < size; j++) { sum += A[j, i] * x[j]; } tmp[i] = alpha * sum + beta * y[i]; } y.Assign(tmp); }
public void Dtrmv(Boolean isUpperTriangular, Boolean transposeA, Boolean isUnitTriangular, DoubleMatrix2D A, DoubleMatrix1D x) { if (transposeA) { A = A.ViewDice(); isUpperTriangular = !isUpperTriangular; } Property.DEFAULT.CheckSquare(A); int size = A.Rows; if (size != x.Size) { throw new ArgumentException(A.ToStringShort() + ", " + x.ToStringShort()); } DoubleMatrix1D b = x.Like(); DoubleMatrix1D y = x.Like(); if (isUnitTriangular) { y.Assign(1); } else { for (int i = 0; i < size; i++) { y[i] = A[i, i]; } } for (int i = 0; i < size; i++) { double sum = 0; if (!isUpperTriangular) { for (int j = 0; j < i; j++) { sum += A[i, j] * x[j]; } sum += y[i] * x[i]; } else { sum += y[i] * x[i]; for (int j = i + 1; j < size; j++) { sum += A[i, j] * x[j]; } } b[i] = sum; } x.Assign(b); }
public void Dgemm(bool transposeA, bool transposeB, double alpha, DoubleMatrix2D A, DoubleMatrix2D B, double beta, DoubleMatrix2D C) { /* * determine how to split and parallelize best into blocks * if more B.columns than tasks --> split B.columns, as follows: * * xx|xx|xxx B * xx|xx|xxx * xx|xx|xxx * A * xxx xx|xx|xxx C * xxx xx|xx|xxx * xxx xx|xx|xxx * xxx xx|xx|xxx * xxx xx|xx|xxx * * if less B.columns than tasks --> split A.rows, as follows: * * xxxxxxx B * xxxxxxx * xxxxxxx * A * xxx xxxxxxx C * xxx xxxxxxx * --- ------- * xxx xxxxxxx * xxx xxxxxxx * --- ------- * xxx xxxxxxx * */ if (transposeA) { Dgemm(false, transposeB, alpha, A.ViewDice(), B, beta, C); return; } if (transposeB) { Dgemm(transposeA, false, alpha, A, B.ViewDice(), beta, C); return; } int m = A.Rows; int n = A.Columns; int p = B.Columns; if (B.Rows != n) { throw new ArgumentException("Matrix2D inner dimensions must agree:" + A.ToStringShort() + ", " + B.ToStringShort()); } if (C.Rows != m || C.Columns != p) { throw new ArgumentException("Incompatibel result matrix: " + A.ToStringShort() + ", " + B.ToStringShort() + ", " + C.ToStringShort()); } if (A == C || B == C) { throw new ArgumentException("Matrices must not be identical"); } long flops = 2L * m * n * p; int noOfTasks = (int)System.Math.Min(flops / 30000, this.maxThreads); // each thread should process at least 30000 flops Boolean splitB = (p >= noOfTasks); int width = splitB ? p : m; noOfTasks = System.Math.Min(width, noOfTasks); if (noOfTasks < 2) { // parallelization doesn't pay off (too much start up overhead) seqBlas.Dgemm(transposeA, transposeB, alpha, A, B, beta, C); return; } // set up concurrent tasks int span = width / noOfTasks; //FJTask[] subTasks = new FJTask[noOfTasks]; for (int i = 0; i < noOfTasks; i++) { int offset = i * span; if (i == noOfTasks - 1) { span = width - span * i; // last span may be a bit larger } DoubleMatrix2D AA, BB, CC; if (splitB) { // split B along columns into blocks AA = A; BB = B.ViewPart(0, offset, n, span); CC = C.ViewPart(0, offset, m, span); } else { // split A along rows into blocks AA = A.ViewPart(offset, 0, span, n); BB = B; CC = C.ViewPart(offset, 0, span, p); } Action task = (() => { seqBlas.Dgemm(transposeA, transposeB, alpha, AA, BB, beta, CC); }); // run tasks and wait for completion try { this.smp.TaskGroup.QueueTask(() => task()); } catch (TaskCanceledException exc) { } } }