Author: dlyubimov
Date: Sun Dec 18 05:01:32 2011
New Revision: 1220335
URL: http://svn.apache.org/viewvc?rev=1220335&view=rev
Log:
MAHOUT-922:adding Distributed cache broadcast option for B'
Modified:
mahout/trunk/core/src/main/java/org/apache/mahout/common/iterator/sequencefile/SequenceFileDirIterator.java
mahout/trunk/core/src/main/java/org/apache/mahout/math/hadoop/stochasticsvd/ABtDenseOutJob.java
mahout/trunk/core/src/main/java/org/apache/mahout/math/hadoop/stochasticsvd/ABtJob.java
mahout/trunk/core/src/main/java/org/apache/mahout/math/hadoop/stochasticsvd/SSVDCli.java
mahout/trunk/core/src/main/java/org/apache/mahout/math/hadoop/stochasticsvd/SSVDSolver.java
mahout/trunk/core/src/test/java/org/apache/mahout/math/hadoop/stochasticsvd/LocalSSVDSolverDenseTest.java
mahout/trunk/core/src/test/java/org/apache/mahout/math/hadoop/stochasticsvd/LocalSSVDSolverSparseSequentialTest.java
Modified:
mahout/trunk/core/src/main/java/org/apache/mahout/common/iterator/sequencefile/SequenceFileDirIterator.java
URL:
http://svn.apache.org/viewvc/mahout/trunk/core/src/main/java/org/apache/mahout/common/iterator/sequencefile/SequenceFileDirIterator.java?rev=1220335&r1=1220334&r2=1220335&view=diff
==============================================================================
---
mahout/trunk/core/src/main/java/org/apache/mahout/common/iterator/sequencefile/SequenceFileDirIterator.java
(original)
+++
mahout/trunk/core/src/main/java/org/apache/mahout/common/iterator/sequencefile/SequenceFileDirIterator.java
Sun Dec 18 05:01:32 2011
@@ -57,7 +57,8 @@ public final class SequenceFileDirIterat
FileStatus[] statuses = HadoopUtil.getFileStatus(path, pathType, filter,
ordering, conf);
- Iterator<FileStatus> fileStatusIterator = Iterators.forArray(statuses);
+ Iterator<FileStatus> fileStatusIterator =
+ Iterators.forArray(statuses == null ? new FileStatus[0] : statuses);
iterators = Lists.newArrayList();
Modified:
mahout/trunk/core/src/main/java/org/apache/mahout/math/hadoop/stochasticsvd/ABtDenseOutJob.java
URL:
http://svn.apache.org/viewvc/mahout/trunk/core/src/main/java/org/apache/mahout/math/hadoop/stochasticsvd/ABtDenseOutJob.java?rev=1220335&r1=1220334&r2=1220335&view=diff
==============================================================================
---
mahout/trunk/core/src/main/java/org/apache/mahout/math/hadoop/stochasticsvd/ABtDenseOutJob.java
(original)
+++
mahout/trunk/core/src/main/java/org/apache/mahout/math/hadoop/stochasticsvd/ABtDenseOutJob.java
Sun Dec 18 05:01:32 2011
@@ -29,7 +29,10 @@ import java.util.regex.Matcher;
import org.apache.commons.lang.Validate;
import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.filecache.DistributedCache;
+import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.LocalFileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.SequenceFile;
@@ -63,6 +66,7 @@ import org.apache.mahout.math.hadoop.sto
public class ABtDenseOutJob {
public static final String PROP_BT_PATH = "ssvd.Bt.path";
+ public static final String PROP_BT_BROADCAST = "ssvd.Bt.broadcast";
private ABtDenseOutJob() {
}
@@ -94,6 +98,8 @@ public class ABtDenseOutJob {
private int aRowCount;
private int kp;
private int blockHeight;
+ private boolean distributedBt;
+ private Path btLocalPath;
@Override
protected void map(Writable key, VectorWritable value, Context context)
@@ -114,8 +120,7 @@ public class ABtDenseOutJob {
aCols[i].setQuick(aRowCount, vec.getQuick(i));
}
} else if (vec.size() > 0) {
- for (Iterator<Vector.Element> vecIter = vec.iterateNonZero(); vecIter
- .hasNext();) {
+ for (Iterator<Vector.Element> vecIter = vec.iterateNonZero();
vecIter.hasNext();) {
Vector.Element vecEl = vecIter.next();
int i = vecEl.index();
extendAColIfNeeded(i, aRowCount + 1);
@@ -133,8 +138,7 @@ public class ABtDenseOutJob {
} else if (aCols[col].size() < rowCount) {
Vector newVec =
new SequentialAccessSparseVector(rowCount + blockHeight,
- aCols[col]
- .getNumNondefaultElements() << 1);
+
aCols[col].getNumNondefaultElements() << 1);
newVec.viewPart(0, aCols[col].size()).assign(aCols[col]);
aCols[col] = newVec;
}
@@ -176,14 +180,26 @@ public class ABtDenseOutJob {
*/
for (int pass = 0; pass < numPasses; pass++) {
- btInput =
- new SequenceFileDirIterator<IntWritable, VectorWritable>(btPath,
-
PathType.GLOB,
- null,
- null,
- true,
- context
-
.getConfiguration());
+ if (distributedBt) {
+
+ btInput =
+ new SequenceFileDirIterator<IntWritable,
VectorWritable>(btLocalPath,
+
PathType.LIST,
+ null,
+ null,
+ true,
+ new
Configuration());
+
+ } else {
+
+ btInput =
+ new SequenceFileDirIterator<IntWritable, VectorWritable>(btPath,
+
PathType.GLOB,
+ null,
+ null,
+ true,
+
context.getConfiguration());
+ }
closeables.addFirst(btInput);
int aRowBegin = pass * blockHeight;
@@ -217,8 +233,7 @@ public class ABtDenseOutJob {
continue;
}
int j = -1;
- for (Iterator<Vector.Element> aColIter = aCol.iterateNonZero();
aColIter
- .hasNext();) {
+ for (Iterator<Vector.Element> aColIter = aCol.iterateNonZero();
aColIter.hasNext();) {
Vector.Element aEl = aColIter.next();
j = aEl.index();
@@ -282,6 +297,24 @@ public class ABtDenseOutJob {
blockHeight =
context.getConfiguration().getInt(BtJob.PROP_OUTER_PROD_BLOCK_HEIGHT,
-1);
+ distributedBt = context.getConfiguration().get(PROP_BT_BROADCAST) !=
null;
+ if (distributedBt) {
+
+ Path[] btFiles =
+ DistributedCache.getLocalCacheFiles(context.getConfiguration());
+
+ String btLocalPathStr = "";
+ Validate.notNull(btFiles,
+ "BT input comes empty from distributed cache.");
+
+ for (Path btFile : btFiles) {
+
+ if (btLocalPathStr.length() > 0)
+ btLocalPathStr += Path.SEPARATOR_CHAR;
+ btLocalPathStr += btFile;
+ }
+ btLocalPath = new Path(btLocalPathStr);
+ }
}
}
@@ -303,8 +336,8 @@ public class ABtDenseOutJob {
* management completely and bypass MultipleOutputs entirely.
*/
- private static final NumberFormat NUMBER_FORMAT = NumberFormat
- .getInstance();
+ private static final NumberFormat NUMBER_FORMAT =
+ NumberFormat.getInstance();
static {
NUMBER_FORMAT.setMinimumIntegerDigits(5);
NUMBER_FORMAT.setGroupingUsed(false);
@@ -393,8 +426,8 @@ public class ABtDenseOutJob {
String uniqueFileName = FileOutputFormat.getUniqueFile(context, name,
"");
uniqueFileName = uniqueFileName.replaceFirst("-r-", "-m-");
uniqueFileName =
- uniqueFileName.replaceFirst("\\d+$", Matcher
- .quoteReplacement(NUMBER_FORMAT.format(spw.getTaskId())));
+ uniqueFileName.replaceFirst("\\d+$",
+
Matcher.quoteReplacement(NUMBER_FORMAT.format(spw.getTaskId())));
return new Path(FileOutputFormat.getWorkOutputPath(context),
uniqueFileName);
}
@@ -454,8 +487,9 @@ public class ABtDenseOutJob {
int k,
int p,
int outerProdBlockHeight,
- int numReduceTasks) throws ClassNotFoundException,
- InterruptedException, IOException {
+ int numReduceTasks,
+ boolean broadcastBInput)
+ throws ClassNotFoundException, InterruptedException, IOException {
JobConf oldApiJob = new JobConf(conf);
@@ -492,6 +526,24 @@ public class ABtDenseOutJob {
job.setNumReduceTasks(numReduceTasks);
+ // broadcast Bt files if required.
+ if (broadcastBInput) {
+ job.getConfiguration().set(PROP_BT_BROADCAST, "y");
+
+ FileSystem fs = FileSystem.get(conf);
+ FileStatus[] fstats = fs.globStatus(inputBtGlob);
+ if (fstats != null) {
+ for (FileStatus fstat : fstats) {
+ /*
+ * new api is not enabled yet in our dependencies at this time, still
+ * using deprecated one
+ */
+ DistributedCache.addCacheFile(fstat.getPath().toUri(),
+ job.getConfiguration());
+ }
+ }
+ }
+
job.submit();
job.waitForCompletion(false);
Modified:
mahout/trunk/core/src/main/java/org/apache/mahout/math/hadoop/stochasticsvd/ABtJob.java
URL:
http://svn.apache.org/viewvc/mahout/trunk/core/src/main/java/org/apache/mahout/math/hadoop/stochasticsvd/ABtJob.java?rev=1220335&r1=1220334&r2=1220335&view=diff
==============================================================================
---
mahout/trunk/core/src/main/java/org/apache/mahout/math/hadoop/stochasticsvd/ABtJob.java
(original)
+++
mahout/trunk/core/src/main/java/org/apache/mahout/math/hadoop/stochasticsvd/ABtJob.java
Sun Dec 18 05:01:32 2011
@@ -29,6 +29,8 @@ import java.util.regex.Matcher;
import org.apache.commons.lang.Validate;
import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.filecache.DistributedCache;
+import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
@@ -63,6 +65,7 @@ import org.apache.mahout.math.hadoop.sto
public class ABtJob {
public static final String PROP_BT_PATH = "ssvd.Bt.path";
+ public static final String PROP_BT_BROADCAST = "ssvd.Bt.broadcast";
private ABtJob() {
}
@@ -116,8 +119,7 @@ public class ABtJob {
aCols[i].setQuick(aRowCount, vec.getQuick(i));
}
} else {
- for (Iterator<Vector.Element> vecIter = vec.iterateNonZero(); vecIter
- .hasNext();) {
+ for (Iterator<Vector.Element> vecIter = vec.iterateNonZero();
vecIter.hasNext();) {
Vector.Element vecEl = vecIter.next();
int i = vecEl.index();
extendAColIfNeeded(i, aRowCount + 1);
@@ -130,13 +132,12 @@ public class ABtJob {
private void extendAColIfNeeded(int col, int rowCount) {
if (aCols[col] == null) {
aCols[col] =
- new SequentialAccessSparseVector(rowCount < 10000 ? 10000 :
rowCount,
- 16);
+ new SequentialAccessSparseVector(rowCount < 10000 ? 10000 : rowCount,
+ 1);
} else if (aCols[col].size() < rowCount) {
Vector newVec =
new SequentialAccessSparseVector(rowCount << 1,
- aCols[col]
- .getNumNondefaultElements() << 1);
+
aCols[col].getNumNondefaultElements() << 1);
newVec.viewPart(0, aCols[col].size()).assign(aCols[col]);
aCols[col] = newVec;
}
@@ -159,8 +160,7 @@ public class ABtJob {
continue;
}
int j = -1;
- for (Iterator<Vector.Element> aColIter = aCol.iterateNonZero();
aColIter
- .hasNext(); ) {
+ for (Iterator<Vector.Element> aColIter = aCol.iterateNonZero();
aColIter.hasNext();) {
Vector.Element aEl = aColIter.next();
j = aEl.index();
@@ -180,8 +180,7 @@ public class ABtJob {
// this happens in sparse matrices when last rows are all zeros
// and is subsequently causing shorter Q matrix row count which we
// probably don't want to repair there but rather here.
- Vector yDummy =
- new SequentialAccessSparseVector(kp);
+ Vector yDummy = new SequentialAccessSparseVector(kp);
// outValue.set(yDummy);
for (lastRowIndex += 1; lastRowIndex < aRowCount; lastRowIndex++) {
// outKey.setTaskItemOrdinal(lastRowIndex);
@@ -210,14 +209,42 @@ public class ABtJob {
Validate.notNull(propBtPathStr, "Bt input is not set");
Path btPath = new Path(propBtPathStr);
- btInput =
- new SequenceFileDirIterator<IntWritable, VectorWritable>(btPath,
- PathType.GLOB,
- null,
- null,
- true,
- context
-
.getConfiguration());
+ boolean distributedBt =
+ context.getConfiguration().get(PROP_BT_BROADCAST) != null;
+
+ if (distributedBt) {
+
+ Path[] btFiles =
+ DistributedCache.getLocalCacheFiles(context.getConfiguration());
+
+ // DEBUG: stdout
+ System.out.printf("list of files: " + btFiles);
+
+ String btLocalPath = "";
+ for (Path btFile : btFiles) {
+ if (btLocalPath.length() > 0)
+ btLocalPath += Path.SEPARATOR_CHAR;
+ btLocalPath += btFile;
+ }
+
+ btInput =
+ new SequenceFileDirIterator<IntWritable, VectorWritable>(new
Path(btLocalPath),
+
PathType.LIST,
+ null,
+ null,
+ true,
+
context.getConfiguration());
+
+ } else {
+
+ btInput =
+ new SequenceFileDirIterator<IntWritable, VectorWritable>(btPath,
+
PathType.GLOB,
+ null,
+ null,
+ true,
+
context.getConfiguration());
+ }
// TODO: how do i release all that stuff??
closeables.addFirst(btInput);
OutputCollector<LongWritable, SparseRowBlockWritable> yiBlockCollector =
@@ -261,8 +288,8 @@ public class ABtJob {
// management
// completely and bypass MultipleOutputs entirely.
- private static final NumberFormat NUMBER_FORMAT = NumberFormat
- .getInstance();
+ private static final NumberFormat NUMBER_FORMAT =
+ NumberFormat.getInstance();
static {
NUMBER_FORMAT.setMinimumIntegerDigits(5);
NUMBER_FORMAT.setGroupingUsed(false);
@@ -342,8 +369,8 @@ public class ABtJob {
String uniqueFileName = FileOutputFormat.getUniqueFile(context, name,
"");
uniqueFileName = uniqueFileName.replaceFirst("-r-", "-m-");
uniqueFileName =
- uniqueFileName.replaceFirst("\\d+$", Matcher
- .quoteReplacement(NUMBER_FORMAT.format(spw.getTaskId())));
+ uniqueFileName.replaceFirst("\\d+$",
+
Matcher.quoteReplacement(NUMBER_FORMAT.format(spw.getTaskId())));
return new Path(FileOutputFormat.getWorkOutputPath(context),
uniqueFileName);
}
@@ -403,8 +430,9 @@ public class ABtJob {
int k,
int p,
int outerProdBlockHeight,
- int numReduceTasks) throws ClassNotFoundException,
- InterruptedException, IOException {
+ int numReduceTasks,
+ boolean broadcastBInput)
+ throws ClassNotFoundException, InterruptedException, IOException {
JobConf oldApiJob = new JobConf(conf);
@@ -459,6 +487,23 @@ public class ABtJob {
job.setNumReduceTasks(numReduceTasks);
+ // broadcast Bt files if required.
+ if (broadcastBInput) {
+ job.getConfiguration().set(PROP_BT_BROADCAST, "y");
+
+ FileSystem fs = FileSystem.get(conf);
+ FileStatus[] fstats = fs.globStatus(inputBtGlob);
+ if (fstats != null) {
+ for (FileStatus fstat : fstats) {
+ /*
+ * new api is not enabled yet in our dependencies at this time, still
+ * using deprecated one
+ */
+ DistributedCache.addCacheFile(fstat.getPath().toUri(), conf);
+ }
+ }
+ }
+
job.submit();
job.waitForCompletion(false);
Modified:
mahout/trunk/core/src/main/java/org/apache/mahout/math/hadoop/stochasticsvd/SSVDCli.java
URL:
http://svn.apache.org/viewvc/mahout/trunk/core/src/main/java/org/apache/mahout/math/hadoop/stochasticsvd/SSVDCli.java?rev=1220335&r1=1220334&r2=1220335&view=diff
==============================================================================
---
mahout/trunk/core/src/main/java/org/apache/mahout/math/hadoop/stochasticsvd/SSVDCli.java
(original)
+++
mahout/trunk/core/src/main/java/org/apache/mahout/math/hadoop/stochasticsvd/SSVDCli.java
Sun Dec 18 05:01:32 2011
@@ -45,12 +45,15 @@ public class SSVDCli extends AbstractJob
addOutputOption();
addOption("rank", "k", "decomposition rank", true);
addOption("oversampling", "p", "oversampling", String.valueOf(15));
- addOption("blockHeight", "r", "Y block height (must be > (k+p))",
String.valueOf(10000));
+ addOption("blockHeight",
+ "r",
+ "Y block height (must be > (k+p))",
+ String.valueOf(10000));
addOption("outerProdBlockHeight",
"oh",
"block height of outer products during multiplication, increase
for sparse inputs",
String.valueOf(30000));
- addOption("abtBlockHeight",
+ addOption("abtBlockHeight",
"abth",
"block height of Y_i in ABtJob during AB' multiplication,
increase for extremely sparse inputs",
String.valueOf(200000));
@@ -73,6 +76,10 @@ public class SSVDCli extends AbstractJob
"q",
"number of additional power iterations (0..2 is good)",
String.valueOf(0));
+ addOption("broadcast",
+ "br",
+ "whether use distributed cache to broadcast matrices wherever
possible",
+ String.valueOf(true));
addOption(DefaultOptionCreator.overwriteOption().create());
Map<String, String> pargs = parseArguments(args);
@@ -92,6 +99,7 @@ public class SSVDCli extends AbstractJob
boolean cUHalfSigma = Boolean.parseBoolean(pargs.get("--uHalfSigma"));
boolean cVHalfSigma = Boolean.parseBoolean(pargs.get("--vHalfSigma"));
int reduceTasks = Integer.parseInt(pargs.get("--reduceTasks"));
+ boolean broadcast = Boolean.parseBoolean(pargs.get("--broadcast"));
boolean overwrite =
pargs.containsKey(keyFor(DefaultOptionCreator.OVERWRITE_OPTION));
@@ -116,6 +124,7 @@ public class SSVDCli extends AbstractJob
solver.setOuterBlockHeight(h);
solver.setAbtBlockHeight(abh);
solver.setQ(q);
+ solver.setBroadcast(broadcast);
solver.setOverwrite(overwrite);
solver.run();
@@ -128,14 +137,16 @@ public class SSVDCli extends AbstractJob
SequenceFile.Writer sigmaW = null;
try {
- sigmaW = SequenceFile.createWriter(fs,
- conf,
- getOutputPath("sigma"),
- NullWritable.class,
- VectorWritable.class);
+ sigmaW =
+ SequenceFile.createWriter(fs,
+ conf,
+ getOutputPath("sigma"),
+ NullWritable.class,
+ VectorWritable.class);
Writable sValues =
- new VectorWritable(new DenseVector(Arrays.copyOf(solver
- .getSingularValues(), k), true));
+ new VectorWritable(new
DenseVector(Arrays.copyOf(solver.getSingularValues(),
+ k),
+ true));
sigmaW.append(NullWritable.get(), sValues);
} finally {
Modified:
mahout/trunk/core/src/main/java/org/apache/mahout/math/hadoop/stochasticsvd/SSVDSolver.java
URL:
http://svn.apache.org/viewvc/mahout/trunk/core/src/main/java/org/apache/mahout/math/hadoop/stochasticsvd/SSVDSolver.java?rev=1220335&r1=1220334&r2=1220335&view=diff
==============================================================================
---
mahout/trunk/core/src/main/java/org/apache/mahout/math/hadoop/stochasticsvd/SSVDSolver.java
(original)
+++
mahout/trunk/core/src/main/java/org/apache/mahout/math/hadoop/stochasticsvd/SSVDSolver.java
Sun Dec 18 05:01:32 2011
@@ -117,6 +117,7 @@ public class SSVDSolver {
private boolean cUHalfSigma;
private boolean cVHalfSigma;
private boolean overwrite;
+ private boolean broadcast = true;
/**
* create new SSVD solver. Required parameters are passed to constructor to
@@ -284,6 +285,20 @@ public class SSVDSolver {
this.abtBlockHeight = abtBlockHeight;
}
+ public boolean isBroadcast() {
+ return broadcast;
+ }
+
+ /**
+ * If this property is true, use DestributedCache mechanism to broadcast some
+ * stuff around. May improve efficiency. Default is false.
+ *
+ * @param broadcast
+ */
+ public void setBroadcast(boolean broadcast) {
+ this.broadcast = broadcast;
+ }
+
/**
* run all SSVD jobs.
*
@@ -292,7 +307,7 @@ public class SSVDSolver {
*/
public void run() throws IOException {
- Deque<Closeable> closeables = Lists.<Closeable>newLinkedList();
+ Deque<Closeable> closeables = Lists.<Closeable> newLinkedList();
try {
Class<? extends Writable> labelType =
sniffInputLabelType(inputPath, conf);
@@ -351,7 +366,8 @@ public class SSVDSolver {
k,
p,
abtBlockHeight,
- reduceTasks);
+ reduceTasks,
+ broadcast);
btPath = new Path(outputPath, String.format("Bt-job-%d", i + 1));
@@ -499,7 +515,8 @@ public class SSVDSolver {
if (!fstats[0].isDir()) {
firstSeqFile = fstats[0];
} else {
- firstSeqFile = fs.listStatus(fstats[0].getPath(),
PathFilters.logsCRCFilter())[0];
+ firstSeqFile =
+ fs.listStatus(fstats[0].getPath(), PathFilters.logsCRCFilter())[0];
}
SequenceFile.Reader r = null;
@@ -566,7 +583,6 @@ public class SSVDSolver {
List<double[]> denseData = Lists.newArrayList();
-
/*
* assume it is partitioned output, so we need to read them up in order of
* partitions.
Modified:
mahout/trunk/core/src/test/java/org/apache/mahout/math/hadoop/stochasticsvd/LocalSSVDSolverDenseTest.java
URL:
http://svn.apache.org/viewvc/mahout/trunk/core/src/test/java/org/apache/mahout/math/hadoop/stochasticsvd/LocalSSVDSolverDenseTest.java?rev=1220335&r1=1220334&r2=1220335&view=diff
==============================================================================
---
mahout/trunk/core/src/test/java/org/apache/mahout/math/hadoop/stochasticsvd/LocalSSVDSolverDenseTest.java
(original)
+++
mahout/trunk/core/src/test/java/org/apache/mahout/math/hadoop/stochasticsvd/LocalSSVDSolverDenseTest.java
Sun Dec 18 05:01:32 2011
@@ -132,6 +132,7 @@ public class LocalSSVDSolverDenseTest ex
ssvd.setAbtBlockHeight(400);
ssvd.setOverwrite(true);
ssvd.setQ(q);
+ ssvd.setBroadcast(false);
ssvd.run();
double[] stochasticSValues = ssvd.getSingularValues();
Modified:
mahout/trunk/core/src/test/java/org/apache/mahout/math/hadoop/stochasticsvd/LocalSSVDSolverSparseSequentialTest.java
URL:
http://svn.apache.org/viewvc/mahout/trunk/core/src/test/java/org/apache/mahout/math/hadoop/stochasticsvd/LocalSSVDSolverSparseSequentialTest.java?rev=1220335&r1=1220334&r2=1220335&view=diff
==============================================================================
---
mahout/trunk/core/src/test/java/org/apache/mahout/math/hadoop/stochasticsvd/LocalSSVDSolverSparseSequentialTest.java
(original)
+++
mahout/trunk/core/src/test/java/org/apache/mahout/math/hadoop/stochasticsvd/LocalSSVDSolverSparseSequentialTest.java
Sun Dec 18 05:01:32 2011
@@ -152,6 +152,7 @@ public class LocalSSVDSolverSparseSequen
ssvd.setOverwrite(true);
ssvd.setQ(q);
+ ssvd.setBroadcast(true);
ssvd.run();
double[] stochasticSValues = ssvd.getSingularValues();