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 <[email protected]>
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);
+       }
+}

Reply via email to