You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@systemds.apache.org by ba...@apache.org on 2022/04/21 10:17:40 UTC
[systemds] branch main updated: [SYSTEMDS-3353] Sparse TSMM dense row block CSR
This is an automated email from the ASF dual-hosted git repository.
baunsgaard pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/systemds.git
The following commit(s) were added to refs/heads/main by this push:
new ef6651095c [SYSTEMDS-3353] Sparse TSMM dense row block CSR
ef6651095c is described below
commit ef6651095cbf871128289cf04f5ea16c4e3532f9
Author: baunsgaard <ba...@tugraz.at>
AuthorDate: Wed Apr 20 15:11:28 2022 +0200
[SYSTEMDS-3353] Sparse TSMM dense row block CSR
This commit fixes a bug where CSR is not supported if it contains
filled dense rows in Sparse TSMM Left.
Closes #1592
---
.../org/apache/sysds/runtime/data/SparseBlock.java | 2 +
.../runtime/matrix/data/LibMatrixBincell.java | 2 +
.../sysds/runtime/matrix/data/LibMatrixMult.java | 12 ++-
.../sysds/runtime/matrix/data/MatrixBlock.java | 3 +
src/test/java/org/apache/sysds/test/TestUtils.java | 2 +-
.../sysds/test/component/matrix/TSMMTest.java | 101 +++++++++++++++++++++
6 files changed, 118 insertions(+), 4 deletions(-)
diff --git a/src/main/java/org/apache/sysds/runtime/data/SparseBlock.java b/src/main/java/org/apache/sysds/runtime/data/SparseBlock.java
index d876946be6..60b34b9e78 100644
--- a/src/main/java/org/apache/sysds/runtime/data/SparseBlock.java
+++ b/src/main/java/org/apache/sysds/runtime/data/SparseBlock.java
@@ -447,6 +447,8 @@ public abstract class SparseBlock implements Serializable
* returned by indexes(r) and values(r). If no such value exists,
* this call returns -1.
*
+ * Note if CSR the pos(r) is subtracted from the result.
+ *
* @param r row index starting at 0
* @param c column index starting at 0
* @return position of the first column index greater than or equal to column c in row r
diff --git a/src/main/java/org/apache/sysds/runtime/matrix/data/LibMatrixBincell.java b/src/main/java/org/apache/sysds/runtime/matrix/data/LibMatrixBincell.java
index 4651165f2b..43ba3791a4 100644
--- a/src/main/java/org/apache/sysds/runtime/matrix/data/LibMatrixBincell.java
+++ b/src/main/java/org/apache/sysds/runtime/matrix/data/LibMatrixBincell.java
@@ -1638,6 +1638,8 @@ public class LibMatrixBincell {
if( op.fn instanceof Multiply ) { //skip empty
//skip empty: merge-join (with inner join semantics)
//similar to sorted list intersection
+ if(result.getSparseBlock() == null)
+ result.allocateSparseRowsBlock();
SparseBlock sblock = result.getSparseBlock();
sblock.allocate(resultRow, Math.min(size1, size2), result.clen);
while( p1 < size1 && p2 < size2 ) {
diff --git a/src/main/java/org/apache/sysds/runtime/matrix/data/LibMatrixMult.java b/src/main/java/org/apache/sysds/runtime/matrix/data/LibMatrixMult.java
index 0e003cad5f..674bb35b1d 100644
--- a/src/main/java/org/apache/sysds/runtime/matrix/data/LibMatrixMult.java
+++ b/src/main/java/org/apache/sysds/runtime/matrix/data/LibMatrixMult.java
@@ -2043,9 +2043,15 @@ public class LibMatrixMult
int alen = a.size(r);
double[] avals = a.values(r);
if( alen == n ) { //dense row
- for( int i=rl; i<ru; i++ ) {
- vectMultiplyAdd(avals[i], avals,
- c.values(i), i, c.pos(i) + i, n-i);
+ final int apos = a.pos(r);
+ for (int i = rl; i < ru; i++){
+ double[] cvals = c.values(i);
+ int cix = c.pos(i);
+ double val = avals[i + apos];
+ for(int j = i ; j < ru; j++){
+ double d = val * avals[j + apos];
+ cvals[cix + j] +=d;
+ }
}
}
else { //non-full sparse row
diff --git a/src/main/java/org/apache/sysds/runtime/matrix/data/MatrixBlock.java b/src/main/java/org/apache/sysds/runtime/matrix/data/MatrixBlock.java
index 5df5d62e72..d65a6d548b 100644
--- a/src/main/java/org/apache/sysds/runtime/matrix/data/MatrixBlock.java
+++ b/src/main/java/org/apache/sysds/runtime/matrix/data/MatrixBlock.java
@@ -1279,6 +1279,8 @@ public class MatrixBlock extends MatrixValue implements CacheBlock, Externalizab
rptr, indexes, values, lnnz);
}
else {
+ // remember number non zeros.
+ long nnzTemp = getNonZeros();
//fallback to less-memory efficient MCSR format,
//which however allows much larger sparse matrices
if( !allocateSparseRowsBlock() )
@@ -1295,6 +1297,7 @@ public class MatrixBlock extends MatrixValue implements CacheBlock, Externalizab
for( int j=0; j<n; j++ )
sblock.append(i, j, avals[aix+j]);
}
+ nonZeros = nnzTemp;
}
//update nnz and cleanup dense block
diff --git a/src/test/java/org/apache/sysds/test/TestUtils.java b/src/test/java/org/apache/sysds/test/TestUtils.java
index ace1c10726..f367032467 100644
--- a/src/test/java/org/apache/sysds/test/TestUtils.java
+++ b/src/test/java/org/apache/sysds/test/TestUtils.java
@@ -870,7 +870,7 @@ public class TestUtils
}
else if(actualMatrix.isEmpty()) {
if(expectedMatrix.getNumRows() < 10)
- fail(message + "\nThe expected output is empty while the actual matrix is not\n" + expectedMatrix + "\n\n"
+ fail(message + "\nThe actual output is empty while the expected matrix is not\nexpected:" + expectedMatrix + "\n\n"
+ "actual:" + actualMatrix);
fail(message + "\nThe actual output is empty while the expected matrix is not");
}
diff --git a/src/test/java/org/apache/sysds/test/component/matrix/TSMMTest.java b/src/test/java/org/apache/sysds/test/component/matrix/TSMMTest.java
new file mode 100644
index 0000000000..d195ea952b
--- /dev/null
+++ b/src/test/java/org/apache/sysds/test/component/matrix/TSMMTest.java
@@ -0,0 +1,101 @@
+/*
+ * 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.sysds.test.component.matrix;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.sysds.lops.MMTSJ.MMTSJType;
+import org.apache.sysds.runtime.matrix.data.MatrixBlock;
+import org.apache.sysds.test.TestUtils;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(value = Parameterized.class)
+public class TSMMTest {
+
+ protected static final Log LOG = LogFactory.getLog(TSMMTest.class.getName());
+
+ @Parameterized.Parameter
+ public MatrixBlock in;
+ @Parameterized.Parameter(1)
+ public int k;
+
+ @Parameters
+ public static Collection<Object[]> data() {
+ ArrayList<Object[]> tests = new ArrayList<>();
+ MatrixBlock mb;
+ final double[] spar = new double[] {0.3, 0.1, 0.01};
+ final int[] cols = new int[] {10, 6, 4, 3, 2, 1};
+ final int[] threads = new int[] {1, 10};
+ final int[] rows = new int[] {10};
+ for(int i = 0; i < 3; i++) { // seeds
+ for(int s = 0; s < spar.length; s++) {
+ for(int c = 0; c < cols.length; c++) {
+ for(int r = 0; r < rows.length; r++) {
+
+ mb = TestUtils.round(TestUtils.generateTestMatrixBlock(rows[r], cols[c], 1, 10, spar[s], i));
+ for(int t = 0; t < threads.length; t++)
+ tests.add(new Object[] {mb, threads[t]});
+ }
+ }
+
+ }
+ }
+ return tests;
+ }
+
+ @Test
+ public void testTSMMLeftSparseVSDense() {
+ final MMTSJType mType = MMTSJType.LEFT;
+ final MatrixBlock expected = in.transposeSelfMatrixMultOperations(null, mType, k);
+ final boolean isSparse = in.isInSparseFormat();
+
+ if(isSparse) {
+ MatrixBlock m2 = new MatrixBlock();
+ m2.copy(in);
+ m2.sparseToDense();
+ testCompare(expected, m2);
+ }
+ else {
+ MatrixBlock m2 = new MatrixBlock();
+ m2.copy(in);
+ m2.denseToSparse(true);
+ testCompare(expected, m2);
+
+ MatrixBlock m3 = new MatrixBlock();
+ m3.copy(in);
+ m3.copy(in);
+ m3.denseToSparse(false);
+ testCompare(expected, m3);
+ }
+ }
+
+ private void testCompare(MatrixBlock expected, MatrixBlock m2) {
+ final MMTSJType mType = MMTSJType.LEFT;
+ final MatrixBlock actual = m2.transposeSelfMatrixMultOperations(null, mType, k);
+ final String inString = m2.toString();
+ TestUtils.compareMatricesBitAvgDistance(expected, actual, 10L, 256L, inString);
+ }
+}