use of org.apache.sysml.lops.Lop in project incubator-systemml by apache.
the class ReorgOp method constructLops.
@Override
public Lop constructLops() {
// return already created lops
if (getLops() != null)
return getLops();
ExecType et = optFindExecType();
switch(op) {
case TRANSPOSE:
{
Lop lin = getInput().get(0).constructLops();
if (lin instanceof Transform && ((Transform) lin).getOperationType() == OperationTypes.Transpose)
// if input is already a transpose, avoid redundant transpose ops
setLops(lin.getInputs().get(0));
else if (getDim1() == 1 && getDim2() == 1)
// if input of size 1x1, avoid unnecessary transpose
setLops(lin);
else {
// general case
int k = OptimizerUtils.getConstrainedNumThreads(_maxNumThreads);
Transform transform1 = new Transform(lin, HopsTransf2Lops.get(op), getDataType(), getValueType(), et, k);
setOutputDimensions(transform1);
setLineNumbers(transform1);
setLops(transform1);
}
break;
}
case DIAG:
{
Transform transform1 = new Transform(getInput().get(0).constructLops(), HopsTransf2Lops.get(op), getDataType(), getValueType(), et);
setOutputDimensions(transform1);
setLineNumbers(transform1);
setLops(transform1);
break;
}
case REV:
{
Lop rev = null;
if (et == ExecType.MR) {
Lop tmp = new Transform(getInput().get(0).constructLops(), HopsTransf2Lops.get(op), getDataType(), getValueType(), et);
setOutputDimensions(tmp);
setLineNumbers(tmp);
Group group1 = new Group(tmp, Group.OperationTypes.Sort, DataType.MATRIX, getValueType());
setOutputDimensions(group1);
setLineNumbers(group1);
rev = new Aggregate(group1, Aggregate.OperationTypes.Sum, DataType.MATRIX, getValueType(), et);
} else {
// CP/SPARK
rev = new Transform(getInput().get(0).constructLops(), HopsTransf2Lops.get(op), getDataType(), getValueType(), et);
}
setOutputDimensions(rev);
setLineNumbers(rev);
setLops(rev);
break;
}
case RESHAPE:
{
// main, rows, cols, byrow
Lop[] linputs = new Lop[4];
for (int i = 0; i < 4; i++) linputs[i] = getInput().get(i).constructLops();
if (et == ExecType.MR) {
Transform transform1 = new Transform(linputs, HopsTransf2Lops.get(op), getDataType(), getValueType(), et);
setOutputDimensions(transform1);
setLineNumbers(transform1);
Group group1 = new Group(transform1, Group.OperationTypes.Sort, DataType.MATRIX, getValueType());
setOutputDimensions(group1);
setLineNumbers(group1);
Aggregate agg1 = new Aggregate(group1, Aggregate.OperationTypes.Sum, DataType.MATRIX, getValueType(), et);
setOutputDimensions(agg1);
setLineNumbers(agg1);
setLops(agg1);
} else // CP/SPARK
{
Transform transform1 = new Transform(linputs, HopsTransf2Lops.get(op), getDataType(), getValueType(), et);
setOutputDimensions(transform1);
setLineNumbers(transform1);
setLops(transform1);
}
break;
}
case SORT:
{
Hop input = getInput().get(0);
Hop by = getInput().get(1);
Hop desc = getInput().get(2);
Hop ixret = getInput().get(3);
if (et == ExecType.MR) {
if (!(desc instanceof LiteralOp && ixret instanceof LiteralOp)) {
LOG.warn("Unsupported non-constant ordering parameters, using defaults and mark for recompilation.");
setRequiresRecompile();
desc = new LiteralOp(false);
ixret = new LiteralOp(false);
}
// Step 1: extraction (if unknown ncol or multiple columns)
Hop vinput = input;
if (input.getDim2() != 1) {
vinput = new IndexingOp("tmp1", getDataType(), getValueType(), input, new LiteralOp(1L), HopRewriteUtils.createValueHop(input, true), by, by, false, true);
vinput.refreshSizeInformation();
vinput.setOutputBlocksizes(getRowsInBlock(), getColsInBlock());
HopRewriteUtils.copyLineNumbers(this, vinput);
}
// Step 2: Index vector sort
Hop voutput = null;
if (2 * OptimizerUtils.estimateSize(vinput.getDim1(), vinput.getDim2()) > OptimizerUtils.getLocalMemBudget() || FORCE_DIST_SORT_INDEXES) {
// large vector, fallback to MR sort
// sort indexes according to given values
SortKeys sort = new SortKeys(vinput.constructLops(), HopRewriteUtils.getBooleanValueSafe((LiteralOp) desc), SortKeys.OperationTypes.Indexes, vinput.getDataType(), vinput.getValueType(), ExecType.MR);
sort.getOutputParameters().setDimensions(vinput.getDim1(), 1, vinput.getRowsInBlock(), vinput.getColsInBlock(), vinput.getNnz());
setLineNumbers(sort);
// note: this sortindexes includes also the shift by offsets and
// final aggregate because sideways passing of offsets would
// not nicely fit the current instruction model
setLops(sort);
voutput = this;
} else {
// small vector, use in-memory sort
ArrayList<Hop> sinputs = new ArrayList<>();
sinputs.add(vinput);
// by (always vector)
sinputs.add(new LiteralOp(1));
sinputs.add(desc);
// indexreturn (always indexes)
sinputs.add(new LiteralOp(true));
voutput = new ReorgOp("tmp3", getDataType(), getValueType(), ReOrgOp.SORT, sinputs);
HopRewriteUtils.copyLineNumbers(this, voutput);
// explicitly construct CP lop; otherwise there is danger of infinite recursion if forced runtime platform.
voutput.setLops(constructCPOrSparkSortLop(vinput, sinputs.get(1), sinputs.get(2), sinputs.get(3), ExecType.CP, false));
voutput.getLops().getOutputParameters().setDimensions(vinput.getDim1(), vinput.getDim2(), vinput.getRowsInBlock(), vinput.getColsInBlock(), vinput.getNnz());
setLops(voutput.constructLops());
}
// -- done via X' = table(seq(), IX') %*% X;
if (!HopRewriteUtils.getBooleanValueSafe((LiteralOp) ixret)) {
// generate seq
DataGenOp seq = HopRewriteUtils.createSeqDataGenOp(voutput);
seq.setName("tmp4");
seq.refreshSizeInformation();
// select exec type
seq.computeMemEstimate(new MemoTable());
HopRewriteUtils.copyLineNumbers(this, seq);
// generate table
TernaryOp table = new TernaryOp("tmp5", DataType.MATRIX, ValueType.DOUBLE, OpOp3.CTABLE, seq, voutput, new LiteralOp(1L));
table.setOutputBlocksizes(getRowsInBlock(), getColsInBlock());
table.refreshSizeInformation();
// force MR
table.setForcedExecType(ExecType.MR);
HopRewriteUtils.copyLineNumbers(this, table);
table.setDisjointInputs(true);
table.setOutputEmptyBlocks(false);
// generate matrix mult
AggBinaryOp mmult = HopRewriteUtils.createMatrixMultiply(table, input);
// force MR
mmult.setForcedExecType(ExecType.MR);
setLops(mmult.constructLops());
// cleanups
HopRewriteUtils.removeChildReference(table, input);
}
} else if (et == ExecType.SPARK) {
boolean sortRewrite = !FORCE_DIST_SORT_INDEXES && isSortSPRewriteApplicable() && by.getDataType().isScalar();
Lop transform1 = constructCPOrSparkSortLop(input, by, desc, ixret, et, sortRewrite);
setOutputDimensions(transform1);
setLineNumbers(transform1);
setLops(transform1);
} else // CP
{
Lop transform1 = constructCPOrSparkSortLop(input, by, desc, ixret, et, false);
setOutputDimensions(transform1);
setLineNumbers(transform1);
setLops(transform1);
}
break;
}
default:
throw new HopsException("Unsupported lops construction for operation type '" + op + "'.");
}
// add reblock/checkpoint lops if necessary
constructAndSetLopsDataFlowProperties();
return getLops();
}
use of org.apache.sysml.lops.Lop in project incubator-systemml by apache.
the class TernaryOp method constructLopsCtable.
/**
* Method to construct LOPs when op = CTABLE.
*/
private void constructLopsCtable() {
if (_op != OpOp3.CTABLE)
throw new HopsException("Unexpected operation: " + _op + ", expecting " + OpOp3.CTABLE);
/*
* We must handle three different cases: case1 : all three
* inputs are vectors (e.g., F=ctable(A,B,W)) case2 : two
* vectors and one scalar (e.g., F=ctable(A,B)) case3 : one
* vector and two scalars (e.g., F=ctable(A))
*/
// identify the particular case
// F=ctable(A,B,W)
DataType dt1 = getInput().get(0).getDataType();
DataType dt2 = getInput().get(1).getDataType();
DataType dt3 = getInput().get(2).getDataType();
Ctable.OperationTypes ternaryOpOrig = Ctable.findCtableOperationByInputDataTypes(dt1, dt2, dt3);
// Compute lops for all inputs
Lop[] inputLops = new Lop[getInput().size()];
for (int i = 0; i < getInput().size(); i++) {
inputLops[i] = getInput().get(i).constructLops();
}
ExecType et = optFindExecType();
// reset reblock requirement (see MR ctable / construct lops)
setRequiresReblock(false);
if (et == ExecType.CP || et == ExecType.SPARK) {
// for CP we support only ctable expand left
Ctable.OperationTypes ternaryOp = isSequenceRewriteApplicable(true) ? Ctable.OperationTypes.CTABLE_EXPAND_SCALAR_WEIGHT : ternaryOpOrig;
boolean ignoreZeros = false;
if (isMatrixIgnoreZeroRewriteApplicable()) {
// table - rmempty - rshape
ignoreZeros = true;
inputLops[0] = ((ParameterizedBuiltinOp) getInput().get(0)).getTargetHop().getInput().get(0).constructLops();
inputLops[1] = ((ParameterizedBuiltinOp) getInput().get(1)).getTargetHop().getInput().get(0).constructLops();
}
Ctable ternary = new Ctable(inputLops, ternaryOp, getDataType(), getValueType(), ignoreZeros, et);
ternary.getOutputParameters().setDimensions(_dim1, _dim2, getRowsInBlock(), getColsInBlock(), -1);
setLineNumbers(ternary);
// force blocked output in CP (see below), otherwise binarycell
if (et == ExecType.SPARK) {
ternary.getOutputParameters().setDimensions(_dim1, _dim2, -1, -1, -1);
setRequiresReblock(true);
} else
ternary.getOutputParameters().setDimensions(_dim1, _dim2, getRowsInBlock(), getColsInBlock(), -1);
// ternary opt, w/o reblock in CP
setLops(ternary);
} else // MR
{
// for MR we support both ctable expand left and right
Ctable.OperationTypes ternaryOp = isSequenceRewriteApplicable() ? Ctable.OperationTypes.CTABLE_EXPAND_SCALAR_WEIGHT : ternaryOpOrig;
Group group1 = null, group2 = null, group3 = null, group4 = null;
group1 = new Group(inputLops[0], Group.OperationTypes.Sort, getDataType(), getValueType());
group1.getOutputParameters().setDimensions(getDim1(), getDim2(), getRowsInBlock(), getColsInBlock(), getNnz());
setLineNumbers(group1);
Ctable ternary = null;
// create "group" lops for MATRIX inputs
switch(ternaryOp) {
case CTABLE_TRANSFORM:
// F = ctable(A,B,W)
group2 = new Group(inputLops[1], Group.OperationTypes.Sort, getDataType(), getValueType());
group2.getOutputParameters().setDimensions(getDim1(), getDim2(), getRowsInBlock(), getColsInBlock(), getNnz());
setLineNumbers(group2);
group3 = new Group(inputLops[2], Group.OperationTypes.Sort, getDataType(), getValueType());
group3.getOutputParameters().setDimensions(getDim1(), getDim2(), getRowsInBlock(), getColsInBlock(), getNnz());
setLineNumbers(group3);
if (inputLops.length == 3)
ternary = new Ctable(new Lop[] { group1, group2, group3 }, ternaryOp, getDataType(), getValueType(), et);
else
// output dimensions are given
ternary = new Ctable(new Lop[] { group1, group2, group3, inputLops[3], inputLops[4] }, ternaryOp, getDataType(), getValueType(), et);
break;
case CTABLE_TRANSFORM_SCALAR_WEIGHT:
// F = ctable(A,B) or F = ctable(A,B,1)
group2 = new Group(inputLops[1], Group.OperationTypes.Sort, getDataType(), getValueType());
group2.getOutputParameters().setDimensions(getDim1(), getDim2(), getRowsInBlock(), getColsInBlock(), getNnz());
setLineNumbers(group2);
if (inputLops.length == 3)
ternary = new Ctable(new Lop[] { group1, group2, inputLops[2] }, ternaryOp, getDataType(), getValueType(), et);
else
ternary = new Ctable(new Lop[] { group1, group2, inputLops[2], inputLops[3], inputLops[4] }, ternaryOp, getDataType(), getValueType(), et);
break;
case CTABLE_EXPAND_SCALAR_WEIGHT:
// F=ctable(seq(1,N),A) or F = ctable(seq,A,1)
// left 1, right 0 (index of input data)
int left = isSequenceRewriteApplicable(true) ? 1 : 0;
Group group = new Group(getInput().get(left).constructLops(), Group.OperationTypes.Sort, getDataType(), getValueType());
group.getOutputParameters().setDimensions(getDim1(), getDim2(), getRowsInBlock(), getColsInBlock(), getNnz());
if (inputLops.length == 3)
ternary = new Ctable(new Lop[] { // matrix
group, // weight
getInput().get(2).constructLops(), // left
new LiteralOp(left).constructLops() }, ternaryOp, getDataType(), getValueType(), et);
else
ternary = new Ctable(new Lop[] { // matrix
group, // weight
getInput().get(2).constructLops(), // left
new LiteralOp(left).constructLops(), inputLops[3], inputLops[4] }, ternaryOp, getDataType(), getValueType(), et);
break;
case CTABLE_TRANSFORM_HISTOGRAM:
// F=ctable(A,1) or F = ctable(A,1,1)
if (inputLops.length == 3)
ternary = new Ctable(new Lop[] { group1, getInput().get(1).constructLops(), getInput().get(2).constructLops() }, ternaryOp, getDataType(), getValueType(), et);
else
ternary = new Ctable(new Lop[] { group1, getInput().get(1).constructLops(), getInput().get(2).constructLops(), inputLops[3], inputLops[4] }, ternaryOp, getDataType(), getValueType(), et);
break;
case CTABLE_TRANSFORM_WEIGHTED_HISTOGRAM:
// F=ctable(A,1,W)
group3 = new Group(getInput().get(2).constructLops(), Group.OperationTypes.Sort, getDataType(), getValueType());
group3.getOutputParameters().setDimensions(getDim1(), getDim2(), getRowsInBlock(), getColsInBlock(), getNnz());
setLineNumbers(group3);
if (inputLops.length == 3)
ternary = new Ctable(new Lop[] { group1, getInput().get(1).constructLops(), group3 }, ternaryOp, getDataType(), getValueType(), et);
else
ternary = new Ctable(new Lop[] { group1, getInput().get(1).constructLops(), group3, inputLops[3], inputLops[4] }, ternaryOp, getDataType(), getValueType(), et);
break;
default:
throw new HopsException("Invalid ternary operator type: " + _op);
}
// output dimensions are not known at compilation time
ternary.getOutputParameters().setDimensions(_dim1, _dim2, (_dimInputsPresent ? getRowsInBlock() : -1), (_dimInputsPresent ? getColsInBlock() : -1), -1);
setLineNumbers(ternary);
Lop lctable = ternary;
if (!(_disjointInputs || ternaryOp == Ctable.OperationTypes.CTABLE_EXPAND_SCALAR_WEIGHT)) {
// no need for aggregation if (1) input indexed disjoint or one side is sequence w/ 1 increment
group4 = new Group(ternary, Group.OperationTypes.Sort, getDataType(), getValueType());
group4.getOutputParameters().setDimensions(_dim1, _dim2, (_dimInputsPresent ? getRowsInBlock() : -1), (_dimInputsPresent ? getColsInBlock() : -1), -1);
setLineNumbers(group4);
Aggregate agg1 = new Aggregate(group4, HopsAgg2Lops.get(AggOp.SUM), getDataType(), getValueType(), ExecType.MR);
agg1.getOutputParameters().setDimensions(_dim1, _dim2, (_dimInputsPresent ? getRowsInBlock() : -1), (_dimInputsPresent ? getColsInBlock() : -1), -1);
setLineNumbers(agg1);
// kahamSum is used for aggregation but inputs do not have
// correction values
agg1.setupCorrectionLocation(CorrectionLocationType.NONE);
lctable = agg1;
}
setLops(lctable);
// to introduce reblock lop since table itself outputs in blocked format if dims known.
if (!dimsKnown() && !_dimInputsPresent) {
setRequiresReblock(true);
}
}
}
use of org.apache.sysml.lops.Lop in project incubator-systemml by apache.
the class SpoofFusedOp method constructLops.
@Override
public Lop constructLops() {
if (getLops() != null)
return getLops();
ExecType et = optFindExecType();
ArrayList<Lop> inputs = new ArrayList<>();
for (Hop c : getInput()) inputs.add(c.constructLops());
int k = OptimizerUtils.getConstrainedNumThreads(_numThreads);
SpoofFused lop = new SpoofFused(inputs, getDataType(), getValueType(), _class, k, et);
setOutputDimensions(lop);
setLineNumbers(lop);
setLops(lop);
return lop;
}
use of org.apache.sysml.lops.Lop in project incubator-systemml by apache.
the class RewriteConstantFolding method evalScalarOperation.
/**
* In order to (1) prevent unexpected side effects from constant folding and
* (2) for simplicity with regard to arbitrary value type combinations,
* we use the same compilation and runtime for constant folding as we would
* use for actual instruction execution.
*
* @param bop high-level operator
* @return literal op
*/
private LiteralOp evalScalarOperation(Hop bop) {
// Timing time = new Timing( true );
DataOp tmpWrite = new DataOp(TMP_VARNAME, bop.getDataType(), bop.getValueType(), bop, DataOpTypes.TRANSIENTWRITE, TMP_VARNAME);
// generate runtime instruction
Dag<Lop> dag = new Dag<>();
// prevent lops reuse
Recompiler.rClearLops(tmpWrite);
// reconstruct lops
Lop lops = tmpWrite.constructLops();
lops.addToDag(dag);
ArrayList<Instruction> inst = dag.getJobs(null, ConfigurationManager.getDMLConfig());
// execute instructions
ExecutionContext ec = getExecutionContext();
ProgramBlock pb = getProgramBlock();
pb.setInstructions(inst);
pb.execute(ec);
// get scalar result (check before invocation) and create literal according
// to observed scalar output type (not hop type) for runtime consistency
ScalarObject so = (ScalarObject) ec.getVariable(TMP_VARNAME);
LiteralOp literal = null;
switch(so.getValueType()) {
case DOUBLE:
literal = new LiteralOp(so.getDoubleValue());
break;
case INT:
literal = new LiteralOp(so.getLongValue());
break;
case BOOLEAN:
literal = new LiteralOp(so.getBooleanValue());
break;
case STRING:
literal = new LiteralOp(so.getStringValue());
break;
default:
throw new HopsException("Unsupported literal value type: " + bop.getValueType());
}
// cleanup
tmpWrite.getInput().clear();
bop.getParent().remove(tmpWrite);
pb.setInstructions(null);
ec.getVariables().removeAll();
// set literal properties (scalar)
HopRewriteUtils.setOutputParametersForScalar(literal);
return literal;
}
use of org.apache.sysml.lops.Lop in project incubator-systemml by apache.
the class Recompiler method recompile.
/**
* Core internal primitive for the dynamic recompilation of any DAGs/predicate,
* including all variants with slightly different configurations.
*
* @param sb statement block of DAG, null for predicates
* @param hops list of DAG root nodes
* @param vars symbol table
* @param status recompilation status
* @param inplace modify DAG in place, otherwise deep copy
* @param replaceLit replace literals (only applicable on deep copy)
* @param updateStats update statistics, rewrites, and memory estimates
* @param forceEt force a given execution type, null for reset
* @param pred recompile for predicate DAG
* @param et given execution type
* @param tid thread id, 0 for main or before worker creation
* @return modified list of instructions
*/
private static ArrayList<Instruction> recompile(StatementBlock sb, ArrayList<Hop> hops, LocalVariableMap vars, RecompileStatus status, boolean inplace, boolean replaceLit, boolean updateStats, boolean forceEt, boolean pred, ExecType et, long tid) {
// prepare hops dag for recompile
if (!inplace) {
// deep copy hop dag (for non-reversable rewrites)
hops = deepCopyHopsDag(hops);
} else {
// clear existing lops
Hop.resetVisitStatus(hops);
for (Hop hopRoot : hops) rClearLops(hopRoot);
}
// replace scalar reads with literals
if (!inplace && replaceLit) {
Hop.resetVisitStatus(hops);
for (Hop hopRoot : hops) rReplaceLiterals(hopRoot, vars, false);
}
// force exec type (et=null for reset)
if (forceEt) {
Hop.resetVisitStatus(hops);
for (Hop hopRoot : hops) rSetExecType(hopRoot, et);
Hop.resetVisitStatus(hops);
}
// update statistics, rewrites, and mem estimates
if (updateStats) {
// refresh matrix characteristics (update stats)
Hop.resetVisitStatus(hops);
for (Hop hopRoot : hops) rUpdateStatistics(hopRoot, vars);
// dynamic hop rewrites
if (!inplace) {
_rewriter.get().rewriteHopDAG(hops, null);
// update stats after rewrites
Hop.resetVisitStatus(hops);
for (Hop hopRoot : hops) rUpdateStatistics(hopRoot, vars);
}
// refresh memory estimates (based on updated stats,
// before: init memo table with propagated worst-case estimates,
// after: extract worst-case estimates from memo table
Hop.resetVisitStatus(hops);
MemoTable memo = new MemoTable();
memo.init(hops, status);
Hop.resetVisitStatus(hops);
for (Hop hopRoot : hops) hopRoot.refreshMemEstimates(memo);
memo.extract(hops, status);
}
// codegen if enabled
if (ConfigurationManager.isCodegenEnabled() && // not on reset
!(forceEt && et == null) && SpoofCompiler.RECOMPILE_CODEGEN) {
// create deep copy for in-place
if (inplace)
hops = deepCopyHopsDag(hops);
Hop.resetVisitStatus(hops);
hops = SpoofCompiler.optimize(hops, (status == null || !status.isInitialCodegen()));
}
// construct lops
Dag<Lop> dag = new Dag<>();
for (Hop hopRoot : hops) {
Lop lops = hopRoot.constructLops();
lops.addToDag(dag);
}
// generate runtime instructions (incl piggybacking)
ArrayList<Instruction> newInst = dag.getJobs(sb, ConfigurationManager.getDMLConfig());
// defer the explain of instructions after additional modifications
if (DMLScript.EXPLAIN == ExplainType.RECOMPILE_HOPS) {
if (pred)
logExplainPred(hops.get(0), newInst);
else
logExplainDAG(sb, hops, newInst);
}
return newInst;
}
Aggregations