Example #1
0
  @Override
  public boolean compare(Hop that) {
    if (!(that instanceof IndexingOp) || getInput().size() != that.getInput().size()) {
      return false;
    }

    return (getInput().get(0) == that.getInput().get(0)
        && getInput().get(1) == that.getInput().get(1)
        && getInput().get(2) == that.getInput().get(2)
        && getInput().get(3) == that.getInput().get(3)
        && getInput().get(4) == that.getInput().get(4));
  }
  private Lop constructLopsTernaryAggregateRewrite(ExecType et)
      throws HopsException, LopsException {
    Hop input1 = getInput().get(0);
    Hop input11 = input1.getInput().get(0);
    Hop input12 = input1.getInput().get(1);

    Lop ret = null;
    Lop in1 = null;
    Lop in2 = null;
    Lop in3 = null;

    if (input11 instanceof BinaryOp && ((BinaryOp) input11).getOp() == OpOp2.MULT) {
      in1 = input11.getInput().get(0).constructLops();
      in2 = input11.getInput().get(1).constructLops();
      in3 = input12.constructLops();
    } else if (input12 instanceof BinaryOp && ((BinaryOp) input12).getOp() == OpOp2.MULT) {
      in1 = input11.constructLops();
      in2 = input12.getInput().get(0).constructLops();
      in3 = input12.getInput().get(1).constructLops();
    } else {
      in1 = input11.constructLops();
      in2 = input12.constructLops();
      in3 = new LiteralOp(1).constructLops();
    }

    // create new ternary aggregate operator
    int k = OptimizerUtils.getConstrainedNumThreads(_maxNumThreads);
    // The execution type of a unary aggregate instruction should depend on the execution type of
    // inputs to avoid OOM
    // Since we only support matrix-vector and not vector-matrix, checking the execution type of
    // input1 should suffice.
    ExecType et_input = input1.optFindExecType();
    ret =
        new TernaryAggregate(
            in1,
            in2,
            in3,
            Aggregate.OperationTypes.KahanSum,
            Binary.OperationTypes.MULTIPLY,
            DataType.SCALAR,
            ValueType.DOUBLE,
            et_input,
            k);

    return ret;
  }
  private boolean isTernaryAggregateRewriteApplicable() throws HopsException {
    boolean ret = false;

    // currently we support only sum over binary multiply but potentially
    // it can be generalized to any RC aggregate over two common binary operations
    if (OptimizerUtils.ALLOW_SUM_PRODUCT_REWRITES
        && _direction == Direction.RowCol
        && _op == AggOp.SUM) {
      Hop input1 = getInput().get(0);
      if (input1.getParent().size() == 1
          && // sum single consumer
          input1 instanceof BinaryOp
          && ((BinaryOp) input1).getOp() == OpOp2.MULT
          // As unary agg instruction is not implemented in MR and since MR is in maintenance mode,
          // postponed it.
          && input1.optFindExecType() != ExecType.MR) {
        Hop input11 = input1.getInput().get(0);
        Hop input12 = input1.getInput().get(1);

        if (input11 instanceof BinaryOp && ((BinaryOp) input11).getOp() == OpOp2.MULT) {
          // ternary, arbitrary matrices but no mv/outer operations.
          ret =
              HopRewriteUtils.isEqualSize(input11.getInput().get(0), input1)
                  && HopRewriteUtils.isEqualSize(input11.getInput().get(1), input1)
                  && HopRewriteUtils.isEqualSize(input12, input1);
        } else if (input12 instanceof BinaryOp && ((BinaryOp) input12).getOp() == OpOp2.MULT) {
          // ternary, arbitrary matrices but no mv/outer operations.
          ret =
              HopRewriteUtils.isEqualSize(input12.getInput().get(0), input1)
                  && HopRewriteUtils.isEqualSize(input12.getInput().get(1), input1)
                  && HopRewriteUtils.isEqualSize(input11, input1);
        } else {
          // binary, arbitrary matrices but no mv/outer operations.
          ret = HopRewriteUtils.isEqualSize(input11, input12);
        }
      }
    }

    return ret;
  }
  private boolean isUnaryAggregateOuterRewriteApplicable() {
    boolean ret = false;
    Hop input = getInput().get(0);

    if (input instanceof BinaryOp && ((BinaryOp) input).isOuterVectorOperator()) {
      // for special cases, we need to hold the broadcast twice in order to allow for
      // an efficient binary search over a plain java array
      double factor =
          (isCompareOperator(((BinaryOp) input).getOp())
                  && (_direction == Direction.Row
                      || _direction == Direction.Col
                      || _direction == Direction.RowCol)
                  && (_op == AggOp.SUM))
              ? 2.0
              : 1.0;

      factor +=
          (isCompareOperator(((BinaryOp) input).getOp())
                  && (_direction == Direction.Row || _direction == Direction.Col)
                  && (_op == AggOp.MAXINDEX || _op == AggOp.MININDEX))
              ? 1.0
              : 0.0;

      // note: memory constraint only needs to take the rhs into account because the output
      // is guaranteed to be an aggregate of <=16KB
      Hop right = input.getInput().get(1);
      if ((right.dimsKnown()
              && factor * OptimizerUtils.estimateSize(right.getDim1(), right.getDim2())
                  < OptimizerUtils.getRemoteMemBudgetMap(true)) // dims known and estimate fits
          || (!right.dimsKnown()
              && factor * right.getOutputMemEstimate()
                  < OptimizerUtils.getRemoteMemBudgetMap(
                      true))) // dims unknown but worst-case estimate fits
      {
        ret = true;
      }
    }

    return ret;
  }
Example #5
0
  /**
   * Indicates if the lbound:rbound expressions is of the form "(c * (i - 1) + 1) : (c * i)", where
   * we could use c as a tight size estimate.
   *
   * @param lbound
   * @param ubound
   * @return
   */
  private boolean isBlockIndexingExpression(Hop lbound, Hop ubound) {
    boolean ret = false;
    LiteralOp constant = null;
    DataOp var = null;

    // handle lower bound
    if (lbound instanceof BinaryOp
        && ((BinaryOp) lbound).getOp() == OpOp2.PLUS
        && lbound.getInput().get(1) instanceof LiteralOp
        && HopRewriteUtils.getDoubleValueSafe((LiteralOp) lbound.getInput().get(1)) == 1
        && lbound.getInput().get(0) instanceof BinaryOp) {
      BinaryOp lmult = (BinaryOp) lbound.getInput().get(0);
      if (lmult.getOp() == OpOp2.MULT
          && lmult.getInput().get(0) instanceof LiteralOp
          && lmult.getInput().get(1) instanceof BinaryOp) {
        BinaryOp lminus = (BinaryOp) lmult.getInput().get(1);
        if (lminus.getOp() == OpOp2.MINUS
            && lminus.getInput().get(1) instanceof LiteralOp
            && HopRewriteUtils.getDoubleValueSafe((LiteralOp) lminus.getInput().get(1)) == 1
            && lminus.getInput().get(0) instanceof DataOp) {
          constant = (LiteralOp) lmult.getInput().get(0);
          var = (DataOp) lminus.getInput().get(0);
        }
      }
    }

    // handle upper bound
    if (var != null
        && constant != null
        && ubound instanceof BinaryOp
        && ubound.getInput().get(0) instanceof LiteralOp
        && ubound.getInput().get(1) instanceof DataOp
        && ubound.getInput().get(1).getName().equals(var.getName())) {
      LiteralOp constant2 = (LiteralOp) ubound.getInput().get(0);
      ret =
          (HopRewriteUtils.getDoubleValueSafe(constant)
              == HopRewriteUtils.getDoubleValueSafe(constant2));
    }

    return ret;
  }
  /**
   * This will check if there is sufficient memory locally (twice the size of second matrix, for
   * original and sort data), and remotely (size of second matrix (sorted data)).
   *
   * @return true if sufficient memory
   */
  private boolean isUnaryAggregateOuterSPRewriteApplicable() {
    boolean ret = false;
    Hop input = getInput().get(0);

    if (input instanceof BinaryOp && ((BinaryOp) input).isOuterVectorOperator()) {
      // note: both cases (partitioned matrix, and sorted double array), require to
      // fit the broadcast twice into the local memory budget. Also, the memory
      // constraint only needs to take the rhs into account because the output is
      // guaranteed to be an aggregate of <=16KB

      Hop right = input.getInput().get(1);

      double size =
          right.dimsKnown()
              ? OptimizerUtils.estimateSize(right.getDim1(), right.getDim2())
              : // dims known and estimate fits
              right.getOutputMemEstimate(); // dims unknown but worst-case estimate fits

      if (_op == AggOp.MAXINDEX || _op == AggOp.MININDEX) {
        double memBudgetExec = SparkExecutionContext.getBroadcastMemoryBudget();
        double memBudgetLocal = OptimizerUtils.getLocalMemBudget();

        // basic requirement: the broadcast needs to to fit twice in the remote broadcast memory
        // and local memory budget because we have to create a partitioned broadcast
        // memory and hand it over to the spark context as in-memory object
        ret = (2 * size < memBudgetExec && 2 * size < memBudgetLocal);

      } else {
        if (OptimizerUtils.checkSparkBroadcastMemoryBudget(size)) {
          ret = true;
        }
      }
    }

    return ret;
  }
Example #7
0
 /**
  * @param lbound
  * @param ubound
  * @return
  */
 private long getBlockIndexingExpressionSize(Hop lbound, Hop ubound) {
   // NOTE: ensure consistency with isBlockIndexingExpression
   LiteralOp c = (LiteralOp) ubound.getInput().get(0); // (c*i)
   return HopRewriteUtils.getIntValueSafe(c);
 }