/** * Function to perform LU decomposition on a given matrix. * * @param in matrix object * @return array of matrix blocks * @throws DMLRuntimeException if DMLRuntimeException occurs */ private static MatrixBlock[] computeLU(MatrixObject in) throws DMLRuntimeException { if (in.getNumRows() != in.getNumColumns()) { throw new DMLRuntimeException( "LU Decomposition can only be done on a square matrix. Input matrix is rectangular (rows=" + in.getNumRows() + ", cols=" + in.getNumColumns() + ")"); } Array2DRowRealMatrix matrixInput = DataConverter.convertToArray2DRowRealMatrix(in); // Perform LUP decomposition LUDecomposition ludecompose = new LUDecomposition(matrixInput); RealMatrix P = ludecompose.getP(); RealMatrix L = ludecompose.getL(); RealMatrix U = ludecompose.getU(); // Read the results into native format MatrixBlock mbP = DataConverter.convertToMatrixBlock(P.getData()); MatrixBlock mbL = DataConverter.convertToMatrixBlock(L.getData()); MatrixBlock mbU = DataConverter.convertToMatrixBlock(U.getData()); return new MatrixBlock[] {mbP, mbL, mbU}; }
public static void matmult( MatrixObject left1, MatrixObject right1, MatrixObject output, boolean isLeftTransposed1, boolean isRightTransposed1) throws DMLRuntimeException { if (isInSparseFormat(left1) || isInSparseFormat(right1)) { throw new DMLRuntimeException("Sparse GPU matrix multiplication is not implemented"); } // Since CuBLAS expects inputs in column-major format, // reverse the order of matrix-multiplication and take care of dimension mismatch. MatrixObject left = right1; MatrixObject right = left1; boolean isLeftTransposed = isRightTransposed1; boolean isRightTransposed = isLeftTransposed1; char transa = isLeftTransposed ? 'T' : 'N'; char transb = isRightTransposed ? 'T' : 'N'; // Note: the dimensions are swapped int m = (int) (isLeftTransposed ? left.getNumRows() : left.getNumColumns()); int n = (int) (isRightTransposed ? right.getNumColumns() : right.getNumRows()); int k = (int) (isLeftTransposed ? left.getNumColumns() : left.getNumRows()); int k1 = (int) (isRightTransposed ? right.getNumRows() : right.getNumColumns()); if (k != k1) throw new DMLRuntimeException("Dimension mismatch: " + k + " != " + k1); if (m == -1 || n == -1 || k == -1) throw new DMLRuntimeException("Incorrect dimensions"); double alpha = 1; double beta = 0; int lda = isLeftTransposed ? k : m; int ldb = isRightTransposed ? n : k; int ldc = m; if (!left.getGPUObject().isAllocated() || !right.getGPUObject().isAllocated()) throw new DMLRuntimeException( "One of input is not allocated:" + left.getGPUObject().isAllocated() + " " + right.getGPUObject().isAllocated()); if (!output.getGPUObject().isAllocated()) throw new DMLRuntimeException( "Output is not allocated:" + output.getGPUObject().isAllocated()); Pointer A = ((JCudaObject) left.getGPUObject()).jcudaPointer; Pointer B = ((JCudaObject) right.getGPUObject()).jcudaPointer; Pointer C = ((JCudaObject) output.getGPUObject()).jcudaPointer; JCublas.cublasDgemm(transa, transb, m, n, k, alpha, A, lda, B, ldb, beta, C, ldc); }
/** * @param hop * @param vars * @return * @throws DMLRuntimeException */ private static long getIntValueDataLiteral(Hop hop, LocalVariableMap vars) throws DMLRuntimeException { long value = -1; try { if (hop instanceof LiteralOp) { value = HopRewriteUtils.getIntValue((LiteralOp) hop); } else if (hop instanceof UnaryOp && ((UnaryOp) hop).getOp() == OpOp1.NROW) { // get the dimension information from the matrix object because the hop // dimensions might not have been updated during recompile MatrixObject mo = (MatrixObject) vars.get(hop.getInput().get(0).getName()); value = mo.getNumRows(); } else if (hop instanceof UnaryOp && ((UnaryOp) hop).getOp() == OpOp1.NCOL) { // get the dimension information from the matrix object because the hop // dimensions might not have been updated during recompile MatrixObject mo = (MatrixObject) vars.get(hop.getInput().get(0).getName()); value = mo.getNumColumns(); } else { ScalarObject sdat = (ScalarObject) vars.get(hop.getName()); value = sdat.getLongValue(); } } catch (HopsException ex) { throw new DMLRuntimeException("Failed to get int value for literal replacement", ex); } return value; }
/** * @param c * @param vars * @return * @throws DMLRuntimeException */ private static LiteralOp replaceLiteralFullUnaryAggregate(Hop c, LocalVariableMap vars) throws DMLRuntimeException { LiteralOp ret = null; // full unary aggregate w/ matrix less than 10^6 cells if (c instanceof AggUnaryOp && isReplaceableUnaryAggregate((AggUnaryOp) c) && c.getInput().get(0) instanceof DataOp && vars.keySet().contains(c.getInput().get(0).getName())) { Hop data = c.getInput().get(0); MatrixObject mo = (MatrixObject) vars.get(data.getName()); // get the dimension information from the matrix object because the hop // dimensions might not have been updated during recompile if (mo.getNumRows() * mo.getNumColumns() < REPLACE_LITERALS_MAX_MATRIX_SIZE) { MatrixBlock mBlock = mo.acquireRead(); double value = replaceUnaryAggregate((AggUnaryOp) c, mBlock); mo.release(); // literal substitution (always double) ret = new LiteralOp(value); } } return ret; }
/** * Function to perform Eigen decomposition on a given matrix. Input must be a symmetric matrix. * * @param in matrix object * @return array of matrix blocks * @throws DMLRuntimeException if DMLRuntimeException occurs */ private static MatrixBlock[] computeEigen(MatrixObject in) throws DMLRuntimeException { if (in.getNumRows() != in.getNumColumns()) { throw new DMLRuntimeException( "Eigen Decomposition can only be done on a square matrix. Input matrix is rectangular (rows=" + in.getNumRows() + ", cols=" + in.getNumColumns() + ")"); } Array2DRowRealMatrix matrixInput = DataConverter.convertToArray2DRowRealMatrix(in); EigenDecomposition eigendecompose = new EigenDecomposition(matrixInput); RealMatrix eVectorsMatrix = eigendecompose.getV(); double[][] eVectors = eVectorsMatrix.getData(); double[] eValues = eigendecompose.getRealEigenvalues(); // Sort the eigen values (and vectors) in increasing order (to be compatible w/ LAPACK.DSYEVR()) int n = eValues.length; for (int i = 0; i < n; i++) { int k = i; double p = eValues[i]; for (int j = i + 1; j < n; j++) { if (eValues[j] < p) { k = j; p = eValues[j]; } } if (k != i) { eValues[k] = eValues[i]; eValues[i] = p; for (int j = 0; j < n; j++) { p = eVectors[j][i]; eVectors[j][i] = eVectors[j][k]; eVectors[j][k] = p; } } } MatrixBlock mbValues = DataConverter.convertToMatrixBlock(eValues, true); MatrixBlock mbVectors = DataConverter.convertToMatrixBlock(eVectors); return new MatrixBlock[] {mbValues, mbVectors}; }
/** * @param c * @param vars * @return * @throws DMLRuntimeException */ private static LiteralOp replaceLiteralFullUnaryAggregateRightIndexing( Hop c, LocalVariableMap vars) throws DMLRuntimeException { LiteralOp ret = null; // full unary aggregate w/ indexed matrix less than 10^6 cells if (c instanceof AggUnaryOp && isReplaceableUnaryAggregate((AggUnaryOp) c) && c.getInput().get(0) instanceof IndexingOp && c.getInput().get(0).getInput().get(0) instanceof DataOp) { IndexingOp rix = (IndexingOp) c.getInput().get(0); Hop data = rix.getInput().get(0); Hop rl = rix.getInput().get(1); Hop ru = rix.getInput().get(2); Hop cl = rix.getInput().get(3); Hop cu = rix.getInput().get(4); if (data instanceof DataOp && vars.keySet().contains(data.getName()) && isIntValueDataLiteral(rl, vars) && isIntValueDataLiteral(ru, vars) && isIntValueDataLiteral(cl, vars) && isIntValueDataLiteral(cu, vars)) { long rlval = getIntValueDataLiteral(rl, vars); long ruval = getIntValueDataLiteral(ru, vars); long clval = getIntValueDataLiteral(cl, vars); long cuval = getIntValueDataLiteral(cu, vars); MatrixObject mo = (MatrixObject) vars.get(data.getName()); // get the dimension information from the matrix object because the hop // dimensions might not have been updated during recompile if (mo.getNumRows() * mo.getNumColumns() < REPLACE_LITERALS_MAX_MATRIX_SIZE) { MatrixBlock mBlock = mo.acquireRead(); MatrixBlock mBlock2 = mBlock.sliceOperations( (int) (rlval - 1), (int) (ruval - 1), (int) (clval - 1), (int) (cuval - 1), new MatrixBlock()); double value = replaceUnaryAggregate((AggUnaryOp) c, mBlock2); mo.release(); // literal substitution (always double) ret = new LiteralOp(value); } } } return ret; }
/** * @param c * @param vars * @return * @throws DMLRuntimeException */ private static LiteralOp replaceLiteralValueTypeCastRightIndexing(Hop c, LocalVariableMap vars) throws DMLRuntimeException { LiteralOp ret = null; // as.scalar/right indexing w/ literals/vars and matrix less than 10^6 cells if (c instanceof UnaryOp && ((UnaryOp) c).getOp() == OpOp1.CAST_AS_SCALAR && c.getInput().get(0) instanceof IndexingOp && c.getInput().get(0).getDataType() == DataType.MATRIX) { IndexingOp rix = (IndexingOp) c.getInput().get(0); Hop data = rix.getInput().get(0); Hop rl = rix.getInput().get(1); Hop ru = rix.getInput().get(2); Hop cl = rix.getInput().get(3); Hop cu = rix.getInput().get(4); if (rix.dimsKnown() && rix.getDim1() == 1 && rix.getDim2() == 1 && data instanceof DataOp && vars.keySet().contains(data.getName()) && isIntValueDataLiteral(rl, vars) && isIntValueDataLiteral(ru, vars) && isIntValueDataLiteral(cl, vars) && isIntValueDataLiteral(cu, vars)) { long rlval = getIntValueDataLiteral(rl, vars); long clval = getIntValueDataLiteral(cl, vars); MatrixObject mo = (MatrixObject) vars.get(data.getName()); // get the dimension information from the matrix object because the hop // dimensions might not have been updated during recompile if (mo.getNumRows() * mo.getNumColumns() < REPLACE_LITERALS_MAX_MATRIX_SIZE) { MatrixBlock mBlock = mo.acquireRead(); double value = mBlock.getValue((int) rlval - 1, (int) clval - 1); mo.release(); // literal substitution (always double) ret = new LiteralOp(value); } } } return ret; }
public void setMetaData(String varName, long nrows, long ncols) throws DMLRuntimeException { MatrixObject mo = getMatrixObject(varName); if (mo.getNumRows() == nrows && mo.getNumColumns() == ncols) return; MetaData oldMetaData = mo.getMetaData(); if (oldMetaData == null || !(oldMetaData instanceof MatrixFormatMetaData)) throw new DMLRuntimeException("Metadata not available"); MatrixCharacteristics mc = new MatrixCharacteristics( (long) nrows, (long) ncols, (int) mo.getNumRowsPerBlock(), (int) mo.getNumColumnsPerBlock()); mo.setMetaData( new MatrixFormatMetaData( mc, ((MatrixFormatMetaData) oldMetaData).getOutputInfo(), ((MatrixFormatMetaData) oldMetaData).getInputInfo())); }
public static boolean isInSparseFormat(MatrixObject mo) { if (mo.getGPUObject() != null && mo.getGPUObject().isAllocated()) return mo.getGPUObject().isInSparseFormat(); return MatrixBlock.evalSparseFormatInMemory(mo.getNumRows(), mo.getNumColumns(), mo.getNnz()); }