You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@systemml.apache.org by mb...@apache.org on 2018/07/12 03:59:47 UTC
systemml git commit: [SYSTEMML-2291] Initial sparsity estimator based
on layered graphs
Repository: systemml
Updated Branches:
refs/heads/master a04261d35 -> 58ab12761
[SYSTEMML-2291] Initial sparsity estimator based on layered graphs
Closes #796.
Project: http://git-wip-us.apache.org/repos/asf/systemml/repo
Commit: http://git-wip-us.apache.org/repos/asf/systemml/commit/58ab1276
Tree: http://git-wip-us.apache.org/repos/asf/systemml/tree/58ab1276
Diff: http://git-wip-us.apache.org/repos/asf/systemml/diff/58ab1276
Branch: refs/heads/master
Commit: 58ab127619549b39a91480a79b087033a3f48b3a
Parents: a04261d
Author: Johanna Sommer <jo...@mail-sommer.com>
Authored: Wed Jul 11 20:53:05 2018 -0700
Committer: Matthias Boehm <mb...@gmail.com>
Committed: Wed Jul 11 21:00:34 2018 -0700
----------------------------------------------------------------------
.../sysml/hops/estim/EstimatorLayeredGraph.java | 210 +++++++++++++++++++
1 file changed, 210 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/systemml/blob/58ab1276/src/main/java/org/apache/sysml/hops/estim/EstimatorLayeredGraph.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/hops/estim/EstimatorLayeredGraph.java b/src/main/java/org/apache/sysml/hops/estim/EstimatorLayeredGraph.java
new file mode 100644
index 0000000..fc4a7b9
--- /dev/null
+++ b/src/main/java/org/apache/sysml/hops/estim/EstimatorLayeredGraph.java
@@ -0,0 +1,210 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sysml.hops.estim;
+
+import org.apache.commons.lang.NotImplementedException;
+import org.apache.commons.math3.distribution.ExponentialDistribution;
+import org.apache.commons.math3.random.Well1024a;
+import org.apache.sysml.runtime.matrix.MatrixCharacteristics;
+import org.apache.sysml.runtime.matrix.data.MatrixBlock;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class EstimatorLayeredGraph extends SparsityEstimator {
+
+ private static final int ROUNDS = 128;
+ private final int _rounds;
+
+ public EstimatorLayeredGraph() {
+ this(ROUNDS);
+ }
+
+ public EstimatorLayeredGraph(int rounds) {
+ _rounds = rounds;
+ }
+
+ @Override
+ public double estim(MMNode root) {
+ throw new NotImplementedException();
+ }
+
+ @Override
+ public double estim(MatrixCharacteristics mc1, MatrixCharacteristics mc2) {
+ throw new NotImplementedException();
+ }
+
+ @Override
+ public double estim(MatrixBlock m1, MatrixBlock m2){
+ int layer = 3;
+ LayeredGraph LGraph = new LayeredGraph(m1, m2);
+ //lambda is not the mean, if lambda is 2 hand in 1/2
+ ExponentialDistribution random = new ExponentialDistribution(new Well1024a(), 1);
+ for (int h = 0; h < LGraph.nodes.size(); h++) {
+ if (LGraph.nodes.get(h).getY() == 1) {
+ double[] doubArray = new double[_rounds];
+ for (int g = 0; g < _rounds; g++)
+ doubArray[g] = random.sample();
+ LGraph.nodes.get(h).setVector(doubArray);
+ }
+ }
+ // get r for nodes of upper layer
+ for (int h = 0; h < LGraph.nodes.size(); h++) {
+ if (LGraph.nodes.get(h).getY() == layer) {
+ double[] ret = recr(_rounds, LGraph.nodes.get(h));
+ if(ret != null)
+ LGraph.nodes.get(h).setVector(ret);
+ LGraph.nodes.get(h).setValue(
+ calcNNZ(LGraph.nodes.get(h).getVector(), _rounds));
+ }
+ }
+ //calc final sparsity
+ double nnz = LGraph.nodes.stream().filter(n -> n.getY()==layer)
+ .mapToDouble(n -> n.getValue()).sum();
+ return nnz / m1.getNumRows() / m2.getNumColumns();
+ }
+
+
+ public double[] recr(int numr, Node tempnode) {
+ if (tempnode.getInput().isEmpty())
+ return (tempnode.getY() == 1) ? tempnode.getVector() : null;
+ else if (tempnode.getInput().size() == 1)
+ return recr(numr, tempnode.getInput().get(0));
+ else {
+ return tempnode.getInput().stream()
+ .map(n -> recr(numr, n)).filter(v -> v != null)
+ .reduce((v1,v2) -> min(v1,v2)).get();
+ }
+ }
+
+ private double[] min(double[] v1, double[] v2) {
+ double[] ret = new double[v1.length];
+ for(int i=0; i<v1.length; i++)
+ ret[i] = Math.min(v1[i], v2[i]);
+ return ret;
+ }
+
+ public double calcNNZ(double[] inpvec, int numr) {
+ return (inpvec != null && inpvec.length > 0) ?
+ (numr - 1) / Arrays.stream(inpvec).sum() : 0;
+ }
+
+ private class LayeredGraph {
+ List<Node> nodes = new ArrayList<>();
+
+ public LayeredGraph(MatrixBlock m1, MatrixBlock m2) {
+ createNodes(m1, 1, nodes);
+ createNodes(m2, 2, nodes);
+ }
+ }
+
+ public void createNodes(MatrixBlock m, int mpos, List<Node> nodes) {
+ if( m.isEmpty() )
+ return;
+
+ Node nodeout = null;
+ Node nodein = null;
+ //TODO perf: separate handling sparse and dense
+ //TODO perf: hash lookups for existing nodes
+ for (int i = 0; i < m.getNumRows(); i++) {
+ for (int j = 0; j < m.getNumColumns(); j++) {
+ if (m.getValue(i, j) == 0) continue;
+ boolean alreadyExists = false;
+ boolean alreadyExists2 = false;
+ for (int k = 0; k < nodes.size(); k++) {
+ if (nodes.get(k).getX() == i && nodes.get(k).getY() == mpos) {
+ alreadyExists = true;
+ }
+ }
+ if (!alreadyExists) {
+ nodein = new Node(i, mpos);
+ nodes.add(nodein);
+ } else {
+ for (int k = 0; k < nodes.size(); k++) {
+ if (nodes.get(k).getX() == i && nodes.get(k).getY() == mpos) {
+ nodein = nodes.get(k);
+ }
+ }
+ }
+ for (int k = 0; k < nodes.size(); k++) {
+ if (nodes.get(k).getX() == j && nodes.get(k).getY() == mpos + 1) {
+ alreadyExists2 = true;
+ }
+ }
+ if (!alreadyExists2) {
+ nodeout = new Node(j, mpos + 1);
+ nodes.add(nodeout);
+
+ } else {
+ for (int k = 0; k < nodes.size(); k++) {
+ if (nodes.get(k).getX() == j && nodes.get(k).getY() == mpos + 1) {
+ nodeout = nodes.get(k);
+ }
+ }
+ }
+ nodeout.addnz(nodein);
+ }
+ }
+ }
+
+ private static class Node {
+ int xpos;
+ int ypos;
+ double[] r_vector;
+ List<Node> input = new ArrayList<>();
+ double value;
+
+ public Node(int x, int y) {
+ xpos = x;
+ ypos = y;
+ }
+
+ public void setValue(double inp) {
+ value = inp;
+ }
+
+ public double getValue() {
+ return value;
+ }
+
+ public List<Node> getInput() {
+ return input;
+ }
+
+ public int getX() {
+ return xpos;
+ }
+
+ public int getY() {
+ return ypos;
+ }
+
+ public double[] getVector() {
+ return r_vector;
+ }
+
+ public void setVector(double[] r_input) {
+ r_vector = r_input;
+ }
+
+ public void addnz(Node dest) {
+ input.add(dest);
+ }
+ }
+}