Repository: systemml Updated Branches: refs/heads/master f5de13e7b -> 3f3e927b8
[SYSTEMML-1885] Performance codegen cell agg over compressed matrices This patch substantially improves performance of sparse-safe codegen cell aggregates (sum and sumsq) over compressed matrices by computing only distinct values and scaling these by counts per value. For computing sum(X^2) on the Airline78 dataset (years 2007 and 2008 of the Airline dataset, 3.3GB, dense), this patch improved performance as follows: ULA Base: 1670ms ULA Fused: 269ms ULA Codegen: 157ms CLA Base: 43ms CLA Fused: 41ms CLA Codegen: 1732ms --> 54ms which means a relative improvement of >30x and being very close to hand-coded compressed linear algebra operations. Project: http://git-wip-us.apache.org/repos/asf/systemml/repo Commit: http://git-wip-us.apache.org/repos/asf/systemml/commit/3f3e927b Tree: http://git-wip-us.apache.org/repos/asf/systemml/tree/3f3e927b Diff: http://git-wip-us.apache.org/repos/asf/systemml/diff/3f3e927b Branch: refs/heads/master Commit: 3f3e927b88265be3c265fba896cb149b3aacf3e4 Parents: f5de13e Author: Matthias Boehm <[email protected]> Authored: Mon Sep 4 16:08:16 2017 -0700 Committer: Matthias Boehm <[email protected]> Committed: Mon Sep 4 16:08:36 2017 -0700 ---------------------------------------------------------------------- .../sysml/runtime/codegen/SpoofCellwise.java | 55 +++++++++++----- .../sysml/runtime/compress/ColGroupDDC1.java | 13 ++-- .../sysml/runtime/compress/ColGroupDDC2.java | 11 ++-- .../sysml/runtime/compress/ColGroupOLE.java | 20 +++++- .../sysml/runtime/compress/ColGroupRLE.java | 24 ++++++- .../sysml/runtime/compress/ColGroupValue.java | 14 ++-- .../runtime/compress/CompressedMatrixBlock.java | 9 ++- .../codegen/CompressedCellwiseTest.java | 67 +++++++++++++++++++- .../functions/codegen/CompressedCellwiseSumSq.R | 28 ++++++++ .../codegen/CompressedCellwiseSumSq.dml | 24 +++++++ 10 files changed, 225 insertions(+), 40 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/systemml/blob/3f3e927b/src/main/java/org/apache/sysml/runtime/codegen/SpoofCellwise.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/runtime/codegen/SpoofCellwise.java b/src/main/java/org/apache/sysml/runtime/codegen/SpoofCellwise.java index 5e22406..43a53bf 100644 --- a/src/main/java/org/apache/sysml/runtime/codegen/SpoofCellwise.java +++ b/src/main/java/org/apache/sysml/runtime/codegen/SpoofCellwise.java @@ -32,6 +32,8 @@ import java.util.concurrent.Future; import org.apache.sysml.runtime.DMLRuntimeException; import org.apache.sysml.runtime.compress.BitmapEncoder; +import org.apache.sysml.runtime.compress.ColGroup; +import org.apache.sysml.runtime.compress.ColGroupValue; import org.apache.sysml.runtime.compress.CompressedMatrixBlock; import org.apache.sysml.runtime.functionobjects.Builtin; import org.apache.sysml.runtime.functionobjects.Builtin.BuiltinCode; @@ -119,10 +121,11 @@ public abstract class SpoofCellwise extends SpoofOperator implements Serializabl } //input preparation + MatrixBlock a = inputs.get(0); SideInput[] b = prepInputMatrices(inputs); double[] scalars = prepInputScalars(scalarObjects); - final int m = inputs.get(0).getNumRows(); - final int n = inputs.get(0).getNumColumns(); + final int m = a.getNumRows(); + final int n = a.getNumColumns(); //sparse safe check boolean sparseSafe = isSparseSafe() || (b.length == 0 @@ -132,21 +135,24 @@ public abstract class SpoofCellwise extends SpoofOperator implements Serializabl if( k <= 1 ) //SINGLE-THREADED { if( inputs.get(0) instanceof CompressedMatrixBlock ) - ret = executeCompressedAndAgg((CompressedMatrixBlock)inputs.get(0), b, scalars, m, n, sparseSafe, 0, m); + ret = executeCompressedAndAgg((CompressedMatrixBlock)a, b, scalars, m, n, sparseSafe, 0, m); else if( !inputs.get(0).isInSparseFormat() ) - ret = executeDenseAndAgg(inputs.get(0).getDenseBlock(), b, scalars, m, n, sparseSafe, 0, m); + ret = executeDenseAndAgg(a.getDenseBlock(), b, scalars, m, n, sparseSafe, 0, m); else - ret = executeSparseAndAgg(inputs.get(0).getSparseBlock(), b, scalars, m, n, sparseSafe, 0, m); + ret = executeSparseAndAgg(a.getSparseBlock(), b, scalars, m, n, sparseSafe, 0, m); } else //MULTI-THREADED { try { ExecutorService pool = Executors.newFixedThreadPool( k ); ArrayList<ParAggTask> tasks = new ArrayList<ParAggTask>(); - int nk = UtilFunctions.roundToNext(Math.min(8*k,m/32), k); + int nk = (a instanceof CompressedMatrixBlock) ? k : + UtilFunctions.roundToNext(Math.min(8*k,m/32), k); int blklen = (int)(Math.ceil((double)m/nk)); + if( a instanceof CompressedMatrixBlock ) + blklen = BitmapEncoder.getAlignedBlocksize(blklen); for( int i=0; i<nk & i*blklen<m; i++ ) - tasks.add(new ParAggTask(inputs.get(0), b, scalars, m, n, sparseSafe, i*blklen, Math.min((i+1)*blklen, m))); + tasks.add(new ParAggTask(a, b, scalars, m, n, sparseSafe, i*blklen, Math.min((i+1)*blklen, m))); //execute tasks List<Future<Double>> taskret = pool.invokeAll(tasks); pool.shutdown(); @@ -172,7 +178,7 @@ public abstract class SpoofCellwise extends SpoofOperator implements Serializabl //correction for min/max if( (_aggOp == AggOp.MIN || _aggOp == AggOp.MAX) && sparseSafe - && inputs.get(0).getNonZeros()<inputs.get(0).getNumRows()*inputs.get(0).getNumColumns() ) + && a.getNonZeros()<a.getNumRows()*a.getNumColumns() ) ret = getAggFunction().execute(ret, 0); //unseen 0 might be max or min value return new DoubleObject(ret); @@ -236,8 +242,7 @@ public abstract class SpoofCellwise extends SpoofOperator implements Serializabl ArrayList<ParExecTask> tasks = new ArrayList<ParExecTask>(); int nk = UtilFunctions.roundToNext(Math.min(8*k,m/32), k); int blklen = (int)(Math.ceil((double)m/nk)); - if( a instanceof CompressedMatrixBlock && sparseOut - && k/2*BitmapEncoder.BITMAP_BLOCK_SZ < m) + if( a instanceof CompressedMatrixBlock ) blklen = BitmapEncoder.getAlignedBlocksize(blklen); for( int i=0; i<nk & i*blklen<m; i++ ) tasks.add(new ParExecTask(a, b, scalars, out, m, n, @@ -973,12 +978,32 @@ public abstract class SpoofCellwise extends SpoofOperator implements Serializabl { KahanFunction kplus = (KahanFunction) getAggFunction(); KahanObject kbuff = new KahanObject(0, 0); + KahanObject kbuff2 = new KahanObject(0, 0); - Iterator<IJV> iter = a.getIterator(rl, ru, !sparseSafe); - while( iter.hasNext() ) { - IJV cell = iter.next(); - double val = genexec(cell.getV(), b, scalars, m, n, cell.getI(), cell.getJ()); - kplus.execute2(kbuff, val); + //special case: computation over value-tuples only + if( sparseSafe && b.length==0 && !a.hasUncompressedColGroup() ) { + //note: all remaining groups are guaranteed ColGroupValue + boolean entireGrp = (rl==0 && ru==a.getNumRows()); + for( ColGroup grp : a.getColGroups() ) { + ColGroupValue grpv = (ColGroupValue) grp; + int[] counts = entireGrp ? + grpv.getCounts() : grpv.getCounts(rl, ru); + for(int k=0; k<grpv.getNumValues(); k++) { + kbuff2.set(0, 0); + double in = grpv.sumValues(k, kplus, kbuff2); + double out = genexec(in, b, scalars, m, n, -1, -1); + kplus.execute3(kbuff, out, counts[k]); + } + } + } + //general case of arbitrary side inputs + else { + Iterator<IJV> iter = a.getIterator(rl, ru, !sparseSafe); + while( iter.hasNext() ) { + IJV cell = iter.next(); + double val = genexec(cell.getV(), b, scalars, m, n, cell.getI(), cell.getJ()); + kplus.execute2(kbuff, val); + } } return kbuff._sum; } http://git-wip-us.apache.org/repos/asf/systemml/blob/3f3e927b/src/main/java/org/apache/sysml/runtime/compress/ColGroupDDC1.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/runtime/compress/ColGroupDDC1.java b/src/main/java/org/apache/sysml/runtime/compress/ColGroupDDC1.java index 8fb7d99..d003aa5 100644 --- a/src/main/java/org/apache/sysml/runtime/compress/ColGroupDDC1.java +++ b/src/main/java/org/apache/sysml/runtime/compress/ColGroupDDC1.java @@ -178,17 +178,18 @@ public class ColGroupDDC1 extends ColGroupDDC nnz += ((c[i] = _values[(_data[i]&0xFF)*ncol+colpos])!=0) ? 1 : 0; target.setNonZeros(nnz); } - + @Override public int[] getCounts() { - final int nrow = getNumRows(); + return getCounts(0, getNumRows()); + } + + @Override + public int[] getCounts(int rl, int ru) { final int numVals = getNumValues(); - int[] counts = new int[numVals]; - for( int i=0; i<nrow; i++ ) { + for( int i=rl; i<ru; i++ ) counts[_data[i]&0xFF] ++; - } - return counts; } http://git-wip-us.apache.org/repos/asf/systemml/blob/3f3e927b/src/main/java/org/apache/sysml/runtime/compress/ColGroupDDC2.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/runtime/compress/ColGroupDDC2.java b/src/main/java/org/apache/sysml/runtime/compress/ColGroupDDC2.java index 170eb96..ec7aa18 100644 --- a/src/main/java/org/apache/sysml/runtime/compress/ColGroupDDC2.java +++ b/src/main/java/org/apache/sysml/runtime/compress/ColGroupDDC2.java @@ -183,14 +183,15 @@ public class ColGroupDDC2 extends ColGroupDDC @Override public int[] getCounts() { - final int nrow = getNumRows(); + return getCounts(0, getNumRows()); + } + + @Override + public int[] getCounts(int rl, int ru) { final int numVals = getNumValues(); - int[] counts = new int[numVals]; - for( int i=0; i<nrow; i++ ) { + for( int i=rl; i<ru; i++ ) counts[_data[i]] ++; - } - return counts; } http://git-wip-us.apache.org/repos/asf/systemml/blob/3f3e927b/src/main/java/org/apache/sysml/runtime/compress/ColGroupOLE.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/runtime/compress/ColGroupOLE.java b/src/main/java/org/apache/sysml/runtime/compress/ColGroupOLE.java index 71be538..7574c73 100644 --- a/src/main/java/org/apache/sysml/runtime/compress/ColGroupOLE.java +++ b/src/main/java/org/apache/sysml/runtime/compress/ColGroupOLE.java @@ -230,19 +230,33 @@ public class ColGroupOLE extends ColGroupOffset @Override public int[] getCounts() { final int numVals = getNumValues(); - int[] counts = new int[numVals]; for (int k = 0; k < numVals; k++) { int boff = _ptr[k]; int blen = len(k); - //iterate over bitmap blocks and count partial lengths int count = 0; for (int bix=0; bix < blen; bix+=_data[boff+bix]+1) count += _data[boff+bix]; counts[k] = count; } - + return counts; + } + + @Override + public int[] getCounts(int rl, int ru) { + final int blksz = BitmapEncoder.BITMAP_BLOCK_SZ; + final int numVals = getNumValues(); + int[] counts = new int[numVals]; + for (int k = 0; k < numVals; k++) { + int boff = _ptr[k]; + int blen = len(k); + int bix = skipScanVal(k, rl); + int count = 0; + for( int off=rl; bix < blen && off<ru; bix+=_data[boff+bix]+1, off+=blksz ) + count += _data[boff+bix]; + counts[k] = count; + } return counts; } http://git-wip-us.apache.org/repos/asf/systemml/blob/3f3e927b/src/main/java/org/apache/sysml/runtime/compress/ColGroupRLE.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/runtime/compress/ColGroupRLE.java b/src/main/java/org/apache/sysml/runtime/compress/ColGroupRLE.java index 5b1f804..964e513 100644 --- a/src/main/java/org/apache/sysml/runtime/compress/ColGroupRLE.java +++ b/src/main/java/org/apache/sysml/runtime/compress/ColGroupRLE.java @@ -226,7 +226,6 @@ public class ColGroupRLE extends ColGroupOffset @Override public int[] getCounts() { final int numVals = getNumValues(); - int[] counts = new int[numVals]; for (int k = 0; k < numVals; k++) { int boff = _ptr[k]; @@ -240,7 +239,28 @@ public class ColGroupRLE extends ColGroupOffset } counts[k] = count; } - + return counts; + } + + @Override + public int[] getCounts(int rl, int ru) { + final int numVals = getNumValues(); + int[] counts = new int[numVals]; + for (int k = 0; k < numVals; k++) { + int boff = _ptr[k]; + int blen = len(k); + Pair<Integer,Integer> tmp = skipScanVal(k, rl); + int bix = tmp.getKey(); + int curRunStartOff = tmp.getValue(); + int curRunEnd = tmp.getValue(); + int count = 0; + for ( ; bix<blen && curRunEnd<ru; bix+=2) { + curRunStartOff = curRunEnd + _data[boff+bix]; + curRunEnd = curRunStartOff + _data[boff+bix+1]; + count += Math.min(curRunEnd, ru)-curRunStartOff; + } + counts[k] = count; + } return counts; } http://git-wip-us.apache.org/repos/asf/systemml/blob/3f3e927b/src/main/java/org/apache/sysml/runtime/compress/ColGroupValue.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/runtime/compress/ColGroupValue.java b/src/main/java/org/apache/sysml/runtime/compress/ColGroupValue.java index 4f651eb..febac4c 100644 --- a/src/main/java/org/apache/sysml/runtime/compress/ColGroupValue.java +++ b/src/main/java/org/apache/sysml/runtime/compress/ColGroupValue.java @@ -144,6 +144,8 @@ public abstract class ColGroupValue extends ColGroup public abstract int[] getCounts(); + public abstract int[] getCounts(int rl, int ru); + public int[] getCounts(boolean inclZeros) { int[] counts = getCounts(); if( inclZeros && this instanceof ColGroupOffset ) { @@ -180,7 +182,7 @@ public abstract class ColGroupValue extends ColGroup return -1; } - protected final double sumValues(int valIx) { + public final double sumValues(int valIx) { final int numCols = getNumCols(); final int valOff = valIx * numCols; double val = 0.0; @@ -191,14 +193,16 @@ public abstract class ColGroupValue extends ColGroup return val; } - protected final double sumValues(int valIx, KahanFunction kplus, KahanObject kbuff) { + public final double sumValues(int valIx, KahanFunction kplus) { + return sumValues(valIx, kplus, new KahanObject(0,0)); + } + + public final double sumValues(int valIx, KahanFunction kplus, KahanObject kbuff) { final int numCols = getNumCols(); final int valOff = valIx * numCols; kbuff.set(0, 0); - for( int i = 0; i < numCols; i++ ) { + for( int i = 0; i < numCols; i++ ) kplus.execute2(kbuff, _values[valOff+i]); - } - return kbuff._sum; } http://git-wip-us.apache.org/repos/asf/systemml/blob/3f3e927b/src/main/java/org/apache/sysml/runtime/compress/CompressedMatrixBlock.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/runtime/compress/CompressedMatrixBlock.java b/src/main/java/org/apache/sysml/runtime/compress/CompressedMatrixBlock.java index ced6d62..418394b 100644 --- a/src/main/java/org/apache/sysml/runtime/compress/CompressedMatrixBlock.java +++ b/src/main/java/org/apache/sysml/runtime/compress/CompressedMatrixBlock.java @@ -110,7 +110,7 @@ public class CompressedMatrixBlock extends MatrixBlock implements Externalizable public static boolean INVESTIGATE_ESTIMATES = false; public static boolean ALLOW_DDC_ENCODING = true; private static final boolean LDEBUG = true; //local debug flag - private static final Level LDEBUG_LEVEL = Level.DEBUG; //DEBUG/TRACE for details + private static final Level LDEBUG_LEVEL = Level.INFO; //DEBUG/TRACE for details private static final Log LOG = LogFactory.getLog(CompressedMatrixBlock.class.getName()); @@ -1616,9 +1616,12 @@ public class CompressedMatrixBlock extends MatrixBlock implements Externalizable ((ColGroupValue)grp).getNumValues()); return numVals; } + + public boolean hasUncompressedColGroup() { + return getUncompressedColGroup() != null; + } - private ColGroupUncompressed getUncompressedColGroup() - { + private ColGroupUncompressed getUncompressedColGroup() { for( ColGroup grp : _colGroups ) if( grp instanceof ColGroupUncompressed ) return (ColGroupUncompressed)grp; http://git-wip-us.apache.org/repos/asf/systemml/blob/3f3e927b/src/test/java/org/apache/sysml/test/integration/functions/codegen/CompressedCellwiseTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/sysml/test/integration/functions/codegen/CompressedCellwiseTest.java b/src/test/java/org/apache/sysml/test/integration/functions/codegen/CompressedCellwiseTest.java index f84ec75..641584e 100644 --- a/src/test/java/org/apache/sysml/test/integration/functions/codegen/CompressedCellwiseTest.java +++ b/src/test/java/org/apache/sysml/test/integration/functions/codegen/CompressedCellwiseTest.java @@ -35,9 +35,11 @@ import org.apache.sysml.test.integration.TestConfiguration; import org.apache.sysml.test.utils.TestUtils; public class CompressedCellwiseTest extends AutomatedTestBase -{ +{ private static final String TEST_NAME1 = "CompressedCellwiseMain"; private static final String TEST_NAME2 = "CompressedCellwiseSide"; + private static final String TEST_NAME3 = "CompressedCellwiseSumSq"; + private static final String TEST_DIR = "functions/codegen/"; private static final String TEST_CLASS_DIR = TEST_DIR + CompressedCellwiseTest.class.getSimpleName() + "/"; private final static String TEST_CONF = "SystemML-config-codegen-compress.xml"; @@ -68,6 +70,7 @@ public class CompressedCellwiseTest extends AutomatedTestBase TestUtils.clearAssertionInformation(); addTestConfiguration( TEST_NAME1, new TestConfiguration(TEST_CLASS_DIR, TEST_NAME1, new String[] { "R" }) ); addTestConfiguration( TEST_NAME2, new TestConfiguration(TEST_CLASS_DIR, TEST_NAME2, new String[] { "R" }) ); + addTestConfiguration( TEST_NAME3, new TestConfiguration(TEST_CLASS_DIR, TEST_NAME3, new String[] { "R" }) ); } @Test @@ -252,6 +255,68 @@ public class CompressedCellwiseTest extends AutomatedTestBase //TODO compressed side inputs in spark + //codegen operations over value tuples only + + @Test + public void testCompressedCellwiseSumSqDenseConstCP() { + testCompressedCellwise( TEST_NAME3, SparsityType.DENSE, ValueType.CONST, ExecType.CP ); + } + + @Test + public void testCompressedCellwiseSumSqDenseRandCP() { + testCompressedCellwise( TEST_NAME3, SparsityType.DENSE, ValueType.RAND, ExecType.CP ); + } + + @Test + public void testCompressedCellwiseSumSqDenseRand2CP() { + testCompressedCellwise( TEST_NAME3, SparsityType.DENSE, ValueType.RAND_ROUND_DDC, ExecType.CP ); + } + + @Test + public void testCompressedCellwiseSumSqDenseRand3CP() { + testCompressedCellwise( TEST_NAME3, SparsityType.DENSE, ValueType.RAND_ROUND_OLE, ExecType.CP ); + } + + @Test + public void testCompressedCellwiseSumSqSparseConstCP() { + testCompressedCellwise( TEST_NAME3, SparsityType.SPARSE, ValueType.CONST, ExecType.CP ); + } + + @Test + public void testCompressedCellwiseSumSqSparseRandCP() { + testCompressedCellwise( TEST_NAME3, SparsityType.SPARSE, ValueType.RAND, ExecType.CP ); + } + + @Test + public void testCompressedCellwiseSumSqSparseRand2CP() { + testCompressedCellwise( TEST_NAME3, SparsityType.SPARSE, ValueType.RAND_ROUND_DDC, ExecType.CP ); + } + + @Test + public void testCompressedCellwiseSumSqSparseRand3CP() { + testCompressedCellwise( TEST_NAME3, SparsityType.SPARSE, ValueType.RAND_ROUND_OLE, ExecType.CP ); + } + + @Test + public void testCompressedCellwiseSumSqEmptyConstCP() { + testCompressedCellwise( TEST_NAME3, SparsityType.EMPTY, ValueType.CONST, ExecType.CP ); + } + + @Test + public void testCompressedCellwiseSumSqEmptyRandCP() { + testCompressedCellwise( TEST_NAME3, SparsityType.EMPTY, ValueType.RAND, ExecType.CP ); + } + + @Test + public void testCompressedCellwiseSumSqEmptyRand2CP() { + testCompressedCellwise( TEST_NAME3, SparsityType.EMPTY, ValueType.RAND_ROUND_DDC, ExecType.CP ); + } + + @Test + public void testCompressedCellwiseSumSqEmptyRand3CP() { + testCompressedCellwise( TEST_NAME3, SparsityType.EMPTY, ValueType.RAND_ROUND_OLE, ExecType.CP ); + } + private void testCompressedCellwise(String testname, SparsityType stype, ValueType vtype, ExecType et) { http://git-wip-us.apache.org/repos/asf/systemml/blob/3f3e927b/src/test/scripts/functions/codegen/CompressedCellwiseSumSq.R ---------------------------------------------------------------------- diff --git a/src/test/scripts/functions/codegen/CompressedCellwiseSumSq.R b/src/test/scripts/functions/codegen/CompressedCellwiseSumSq.R new file mode 100644 index 0000000..a31f4cc --- /dev/null +++ b/src/test/scripts/functions/codegen/CompressedCellwiseSumSq.R @@ -0,0 +1,28 @@ +#------------------------------------------------------------- +# +# 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. +# +#------------------------------------------------------------- + +args <- commandArgs(TRUE) +library("Matrix") +library("matrixStats") + +X = readMM(paste(args[1], "X.mtx", sep="")); +R = as.matrix(sum(X^2)); +writeMM(as(R,"CsparseMatrix"), paste(args[2], "R", sep="")); http://git-wip-us.apache.org/repos/asf/systemml/blob/3f3e927b/src/test/scripts/functions/codegen/CompressedCellwiseSumSq.dml ---------------------------------------------------------------------- diff --git a/src/test/scripts/functions/codegen/CompressedCellwiseSumSq.dml b/src/test/scripts/functions/codegen/CompressedCellwiseSumSq.dml new file mode 100644 index 0000000..04e4c32 --- /dev/null +++ b/src/test/scripts/functions/codegen/CompressedCellwiseSumSq.dml @@ -0,0 +1,24 @@ +#------------------------------------------------------------- +# +# 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. +# +#------------------------------------------------------------- + +X = read($1); +R = as.matrix(sum(X^2)); +write(R, $2);
