[SYSTEMML-1833] Fix codegen race conditions and cleanup robustness This patch fixes two codegen issues which led to failures on the ARIMA and MDABivariate algorithms. In detail, this includes (1) a fix of race conditions on variable name creation/usage in multi-threaded parfor contexts with dynamic recompilation, and (2) a fix of cleanup robustness for row-wise templates with partial unknowns (which led to selecting a row template for column vectors and thus invalid generated source code). Additionally, we now also avoid unnecessary dense allocations for empty side vector inputs to row-wise templates because these are only used through cell indexing or dot products.
Furthermore, this also includes a cleanup of the DML and R scripts for MDABivariate statistics (vectorized loops), which simplifies debugging and improves the R performance of these tests by almost 2x. Project: http://git-wip-us.apache.org/repos/asf/systemml/repo Commit: http://git-wip-us.apache.org/repos/asf/systemml/commit/c170374e Tree: http://git-wip-us.apache.org/repos/asf/systemml/tree/c170374e Diff: http://git-wip-us.apache.org/repos/asf/systemml/diff/c170374e Branch: refs/heads/master Commit: c170374e7fb2c709ac07b00caa9536c2da7e6987 Parents: 4b81d0d Author: Matthias Boehm <mboe...@gmail.com> Authored: Wed Aug 9 13:51:38 2017 -0700 Committer: Matthias Boehm <mboe...@gmail.com> Committed: Wed Aug 9 13:52:53 2017 -0700 ---------------------------------------------------------------------- .../sysml/hops/codegen/SpoofCompiler.java | 19 ++++--- .../apache/sysml/hops/codegen/cplan/CNode.java | 4 -- .../sysml/hops/codegen/cplan/CNodeCell.java | 2 +- .../hops/codegen/cplan/CNodeOuterProduct.java | 2 +- .../hops/codegen/template/TemplateCell.java | 2 +- .../sysml/runtime/codegen/SpoofOperator.java | 10 ++-- .../applications/MDABivariateStatsTest.java | 1 + .../functions/codegen/AlgorithmARIMA.java | 52 ++++++++++++++++++++ .../functions/codegen/AlgorithmMDABivar.java | 52 ++++++++++++++++++++ .../applications/mdabivar/MDABivariateStats.R | 35 +++++-------- .../applications/mdabivar/MDABivariateStats.dml | 26 +++------- .../functions/codegen/ZPackageSuite.java | 2 + 12 files changed, 147 insertions(+), 60 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/systemml/blob/c170374e/src/main/java/org/apache/sysml/hops/codegen/SpoofCompiler.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/hops/codegen/SpoofCompiler.java b/src/main/java/org/apache/sysml/hops/codegen/SpoofCompiler.java index 5029802..d5c9618 100644 --- a/src/main/java/org/apache/sysml/hops/codegen/SpoofCompiler.java +++ b/src/main/java/org/apache/sysml/hops/codegen/SpoofCompiler.java @@ -704,15 +704,18 @@ public class SpoofCompiler } } - //remove spurious lookups on main input of cell template - if( tpl instanceof CNodeCell || tpl instanceof CNodeOuterProduct ) { - CNodeData in1 = (CNodeData)tpl.getInput().get(0); - rFindAndRemoveLookup(tpl.getOutput(), in1); - } - else if( tpl instanceof CNodeMultiAgg ) { - CNodeData in1 = (CNodeData)tpl.getInput().get(0); + //remove invalid lookups on main input (all templates) + CNodeData in1 = (CNodeData)tpl.getInput().get(0); + if( tpl instanceof CNodeMultiAgg ) rFindAndRemoveLookupMultiAgg((CNodeMultiAgg)tpl, in1); - } + else + rFindAndRemoveLookup(tpl.getOutput(), in1); + + //remove invalid row templates (e.g., due to partial unknowns) + if( tpl instanceof CNodeRow && (in1.getNumCols() == 1 + || (((CNodeRow)tpl).getRowType()==RowType.NO_AGG + && tpl.getOutput().getDataType().isScalar())) ) + cplans2.remove(e.getKey()); //remove cplan w/ single op and w/o agg if( (tpl instanceof CNodeCell && ((CNodeCell)tpl).getCellType()==CellType.NO_AGG http://git-wip-us.apache.org/repos/asf/systemml/blob/c170374e/src/main/java/org/apache/sysml/hops/codegen/cplan/CNode.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNode.java b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNode.java index 1f91697..ff9103e 100644 --- a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNode.java +++ b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNode.java @@ -75,10 +75,6 @@ public abstract class CNode return _genVar; } - protected static String getCurrentVarName() { - return "TMP"+(_seqVar.getCurrentID()-1); - } - public String getVarname() { return _genVar; } http://git-wip-us.apache.org/repos/asf/systemml/blob/c170374e/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeCell.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeCell.java b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeCell.java index 36cf56f..dd3806d 100644 --- a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeCell.java +++ b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeCell.java @@ -118,7 +118,7 @@ public class CNodeCell extends CNodeTpl tmp = tmp.replace("%BODY_dense%", tmpDense); //return last TMP - tmp = tmp.replace("%OUT%", getCurrentVarName()); + tmp = tmp.replace("%OUT%", _output.getVarname()); //replace meta data information tmp = tmp.replace("%TYPE%", getCellType().name()); http://git-wip-us.apache.org/repos/asf/systemml/blob/c170374e/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeOuterProduct.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeOuterProduct.java b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeOuterProduct.java index 90917f8..b06e9b9 100644 --- a/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeOuterProduct.java +++ b/src/main/java/org/apache/sysml/hops/codegen/cplan/CNodeOuterProduct.java @@ -83,7 +83,7 @@ public class CNodeOuterProduct extends CNodeTpl else { tmp = tmp.replace("%BODY_dense%", ""); tmp = tmp.replace("%BODY_cellwise%", tmpDense); - tmp = tmp.replace("%OUT_cellwise%", getCurrentVarName()); + tmp = tmp.replace("%OUT_cellwise%", _output.getVarname()); } //replace size information tmp = tmp.replace("%LEN%", "len"); http://git-wip-us.apache.org/repos/asf/systemml/blob/c170374e/src/main/java/org/apache/sysml/hops/codegen/template/TemplateCell.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/hops/codegen/template/TemplateCell.java b/src/main/java/org/apache/sysml/hops/codegen/template/TemplateCell.java index b781fd8..c9d97b9 100644 --- a/src/main/java/org/apache/sysml/hops/codegen/template/TemplateCell.java +++ b/src/main/java/org/apache/sysml/hops/codegen/template/TemplateCell.java @@ -275,7 +275,7 @@ public class TemplateCell extends TemplateBase } protected static boolean isValidOperation(Hop hop) - { + { //prepare indicators for binary operations boolean isBinaryMatrixScalar = false; boolean isBinaryMatrixVector = false; http://git-wip-us.apache.org/repos/asf/systemml/blob/c170374e/src/main/java/org/apache/sysml/runtime/codegen/SpoofOperator.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/sysml/runtime/codegen/SpoofOperator.java b/src/main/java/org/apache/sysml/runtime/codegen/SpoofOperator.java index e302012..cff640c 100644 --- a/src/main/java/org/apache/sysml/runtime/codegen/SpoofOperator.java +++ b/src/main/java/org/apache/sysml/runtime/codegen/SpoofOperator.java @@ -93,9 +93,13 @@ public abstract class SpoofOperator implements Serializable if( denseOnly && (in.isInSparseFormat() || !in.isAllocated()) ) { //convert empty or sparse to dense temporary block (note: we don't do //this in place because this block might be used by multiple threads) - b[i-offset] = new SideInput(DataConverter.convertToDoubleVector(in), null, clen); - LOG.warn(getClass().getName()+": Converted "+in.getNumRows()+"x"+in.getNumColumns()+ - ", nnz="+in.getNonZeros()+" sideways input matrix from sparse to dense."); + if( in.getNumColumns()==1 && in.isEmptyBlock(false) ) //dense empty + b[i-offset] = new SideInput(null, null, clen); + else { + b[i-offset] = new SideInput(DataConverter.convertToDoubleVector(in), null, clen); + LOG.warn(getClass().getName()+": Converted "+in.getNumRows()+"x"+in.getNumColumns()+ + ", nnz="+in.getNonZeros()+" sideways input matrix from sparse to dense."); + } } else if( in.isInSparseFormat() && in.isAllocated() ) { b[i-offset] = new SideInput(null, in, clen); http://git-wip-us.apache.org/repos/asf/systemml/blob/c170374e/src/test/java/org/apache/sysml/test/integration/applications/MDABivariateStatsTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/sysml/test/integration/applications/MDABivariateStatsTest.java b/src/test/java/org/apache/sysml/test/integration/applications/MDABivariateStatsTest.java index 3b38504..f635241 100644 --- a/src/test/java/org/apache/sysml/test/integration/applications/MDABivariateStatsTest.java +++ b/src/test/java/org/apache/sysml/test/integration/applications/MDABivariateStatsTest.java @@ -72,6 +72,7 @@ public abstract class MDABivariateStatsTest extends AutomatedTestBase if (scriptType == ScriptType.PYDML) { proArgs.add("-python"); } + proArgs.add("-stats"); proArgs.add("-args"); proArgs.add(input("X")); proArgs.add(Integer.toString(label_index)); http://git-wip-us.apache.org/repos/asf/systemml/blob/c170374e/src/test/java/org/apache/sysml/test/integration/functions/codegen/AlgorithmARIMA.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/sysml/test/integration/functions/codegen/AlgorithmARIMA.java b/src/test/java/org/apache/sysml/test/integration/functions/codegen/AlgorithmARIMA.java new file mode 100644 index 0000000..248eb82 --- /dev/null +++ b/src/test/java/org/apache/sysml/test/integration/functions/codegen/AlgorithmARIMA.java @@ -0,0 +1,52 @@ +/* + * 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.test.integration.functions.codegen; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.io.File; + +import org.apache.sysml.test.integration.applications.ArimaTest; + +@RunWith(value = Parameterized.class) +public class AlgorithmARIMA extends ArimaTest +{ + private final static String LOCAL_TEST_DIR = "functions/codegen/"; + private final static String TEST_CONF = "SystemML-config-codegen.xml"; + private final static File TEST_CONF_FILE = new File(SCRIPT_DIR + LOCAL_TEST_DIR, TEST_CONF); + + public AlgorithmARIMA(int m, int p, int d, int q, int P, int D, int Q, int s, int include_mean, int useJacobi) { + super(m, p, d, q, P, D, Q, s, include_mean, useJacobi); + TEST_CLASS_DIR = TEST_DIR + AlgorithmARIMA.class.getSimpleName() + "/"; + } + + @Test + public void testArimaDml() { + testArima(ScriptType.DML); + } + + @Override + protected File getConfigTemplateFile() { + System.out.println("This test case overrides default configuration with " + TEST_CONF_FILE.getPath()); + return TEST_CONF_FILE; + } +} http://git-wip-us.apache.org/repos/asf/systemml/blob/c170374e/src/test/java/org/apache/sysml/test/integration/functions/codegen/AlgorithmMDABivar.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/sysml/test/integration/functions/codegen/AlgorithmMDABivar.java b/src/test/java/org/apache/sysml/test/integration/functions/codegen/AlgorithmMDABivar.java new file mode 100644 index 0000000..9477234 --- /dev/null +++ b/src/test/java/org/apache/sysml/test/integration/functions/codegen/AlgorithmMDABivar.java @@ -0,0 +1,52 @@ +/* + * 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.test.integration.functions.codegen; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.io.File; + +import org.apache.sysml.test.integration.applications.MDABivariateStatsTest; + +@RunWith(value = Parameterized.class) +public class AlgorithmMDABivar extends MDABivariateStatsTest +{ + private final static String LOCAL_TEST_DIR = "functions/codegen/"; + private final static String TEST_CONF = "SystemML-config-codegen.xml"; + private final static File TEST_CONF_FILE = new File(SCRIPT_DIR + LOCAL_TEST_DIR, TEST_CONF); + + public AlgorithmMDABivar(int n, int m, int li, int lml) { + super(n, m, li, lml); + TEST_CLASS_DIR = TEST_DIR + AlgorithmMDABivar.class.getSimpleName() + "/"; + } + + @Test + public void testMDABivariateStatsDml() { + testMDABivariateStats(ScriptType.DML); + } + + @Override + protected File getConfigTemplateFile() { + System.out.println("This test case overrides default configuration with " + TEST_CONF_FILE.getPath()); + return TEST_CONF_FILE; + } +} http://git-wip-us.apache.org/repos/asf/systemml/blob/c170374e/src/test/scripts/applications/mdabivar/MDABivariateStats.R ---------------------------------------------------------------------- diff --git a/src/test/scripts/applications/mdabivar/MDABivariateStats.R b/src/test/scripts/applications/mdabivar/MDABivariateStats.R index 1844bbb..92605ad 100644 --- a/src/test/scripts/applications/mdabivar/MDABivariateStats.R +++ b/src/test/scripts/applications/mdabivar/MDABivariateStats.R @@ -101,19 +101,19 @@ args <- commandArgs(TRUE) library(Matrix) # input data set -D = readMM(paste(args[1], "X.mtx", sep="")); +D = as.matrix(readMM(paste(args[1], "X.mtx", sep=""))); # label attr id (must be a valid index > 0) label_index = as.integer(args[2]) # feature attributes, column vector of indices -feature_indices = readMM(paste(args[1], "feature_indices.mtx", sep="")) +feature_indices = as.matrix(readMM(paste(args[1], "feature_indices.mtx", sep=""))) # can be either 1 (scale) or 0 (categorical) label_measurement_level = as.integer(args[3]) # measurement levels for features, 0/1 column vector -feature_measurement_levels = readMM(paste(args[1], "feature_measurement_levels.mtx", sep="")) +feature_measurement_levels = as.matrix(readMM(paste(args[1], "feature_measurement_levels.mtx", sep=""))) sz = ncol(D) @@ -180,9 +180,7 @@ featureSTDs = matrix(0, sz, maxNumberOfGroups) if(label_measurement_level == 0){ featureCounts[label_index,1:length(distinct_label_values)] = distinct_label_values - for(i2 in 1:length(distinct_label_values)){ - featureValues[label_index,i2] = i2-labelCorrection - } + featureValues[label_index,1:length(distinct_label_values)] = t(seq(1,length(distinct_label_values))-labelCorrection); } for(i3 in 1:nrow(feature_indices)){ @@ -209,28 +207,19 @@ for(i3 in 1:nrow(feature_indices)){ sz3 = nrow(contingencyTable)*ncol(contingencyTable) - contingencyTableCounts = matrix(0, 1, sz3) - contingencyTableLabelValues = matrix(0, 1, sz3) - contingencyTableFeatureValues = matrix(0, 1, sz3) + tmpLV = (seq(1,nrow(contingencyTable)) %*% matrix(1,1,ncol(contingencyTable))) - labelCorrection; + tmpFV = (matrix(1,nrow(contingencyTable),1) %*% t(seq(1,ncol(contingencyTable)))) - featureCorrection; + contingencyTableLabelValues = matrix(tmpLV, 1, sz3, byrow=TRUE); + contingencyTableFeatureValues = matrix(tmpFV, 1, sz3, byrow=TRUE); - for(i4 in 1:nrow(contingencyTable)){ - for(j in 1:ncol(contingencyTable)){ - #get rid of this, see *1 below - contingencyTableCounts[1, ncol(contingencyTable)*(i4-1)+j] = contingencyTable[i4,j] - - contingencyTableLabelValues[1, ncol(contingencyTable)*(i4-1)+j] = i4-labelCorrection - contingencyTableFeatureValues[1, ncol(contingencyTable)*(i4-1)+j] = j-featureCorrection - } - } + contingencyTableCounts = matrix(contingencyTable, 1, sz3, byrow=TRUE); contingencyTablesCounts[feature_index2,1:sz3] = contingencyTableCounts contingencyTablesLabelValues[feature_index2,1:sz3] = contingencyTableLabelValues contingencyTablesFeatureValues[feature_index2,1:sz3] = contingencyTableFeatureValues featureCounts[feature_index2,1:length(colMarginals)] = colMarginals - for(i5 in 1:length(colMarginals)){ - featureValues[feature_index2,i5] = i5-featureCorrection - } + featureValues[feature_index2,1:length(colMarginals)] = t(seq(1,length(colMarginals)) - featureCorrection); }else{ # label is scale, feature is categorical tests[feature_index2,1] = 2 @@ -243,9 +232,7 @@ for(i3 in 1:nrow(feature_indices)){ stats[feature_index2,1] = pVal featureCounts[feature_index2,1:nrow(frequencies)] = t(frequencies) - for(i6 in 1:nrow(frequencies)){ - featureValues[feature_index2,i6] = i6 - featureCorrection - } + featureValues[feature_index2,1:nrow(frequencies)] = t(seq(1,nrow(frequencies)) - featureCorrection) featureMeans[feature_index2,1:nrow(means)] = t(means) featureSTDs[feature_index2,1:nrow(variances)] = t(sqrt(variances)) } http://git-wip-us.apache.org/repos/asf/systemml/blob/c170374e/src/test/scripts/applications/mdabivar/MDABivariateStats.dml ---------------------------------------------------------------------- diff --git a/src/test/scripts/applications/mdabivar/MDABivariateStats.dml b/src/test/scripts/applications/mdabivar/MDABivariateStats.dml index faf29b6..61ec7f2 100644 --- a/src/test/scripts/applications/mdabivar/MDABivariateStats.dml +++ b/src/test/scripts/applications/mdabivar/MDABivariateStats.dml @@ -101,9 +101,7 @@ featureSTDs = matrix(0, rows=sz, cols=maxNumberOfGroups) if(label_measurement_level == 0){ featureCounts[label_index,1:nrow(distinct_label_values)] = t(distinct_label_values) - parfor(i2 in 1:nrow(distinct_label_values)){ - featureValues[label_index,i2] = i2-labelCorrection - } + featureValues[label_index,1:nrow(distinct_label_values)] = t(seq(1,nrow(distinct_label_values))-labelCorrection); } parfor(i3 in 1:nrow(feature_indices), check=0){ @@ -125,34 +123,26 @@ parfor(i3 in 1:nrow(feature_indices), check=0){ sz3 = nrow(contingencyTable)*ncol(contingencyTable) while(FALSE){} - contingencyTableLabelValues = matrix(0, rows=1, cols=sz3) - contingencyTableFeatureValues = matrix(0, rows=1, cols=sz3) + tmpLV = (seq(1,nrow(contingencyTable)) %*% matrix(1,1,ncol(contingencyTable))) - labelCorrection; + tmpFV = (matrix(1,nrow(contingencyTable),1) %*% t(seq(1,ncol(contingencyTable)))) - featureCorrection; + contingencyTableLabelValues = matrix(tmpLV, rows=1, cols=sz3) + contingencyTableFeatureValues = matrix(tmpFV, rows=1, cols=sz3) - parfor(i4 in 1:nrow(contingencyTable), check=0){ - parfor(j in 1:ncol(contingencyTable), check=0){ - contingencyTableLabelValues[1, ncol(contingencyTable)*(i4-1)+j] = i4-labelCorrection - contingencyTableFeatureValues[1, ncol(contingencyTable)*(i4-1)+j] = j-featureCorrection - } - } contingencyTableCounts = matrix(contingencyTable, rows=1, cols=sz3, byrow=TRUE) - contingencyTablesCounts[feature_index2,1:sz3] = contingencyTableCounts + contingencyTablesCounts[feature_index2,1:sz3] = contingencyTableCounts contingencyTablesLabelValues[feature_index2,1:sz3] = contingencyTableLabelValues contingencyTablesFeatureValues[feature_index2,1:sz3] = contingencyTableFeatureValues featureCounts[feature_index2,1:ncol(colMarginals)] = colMarginals - parfor(i5 in 1:ncol(colMarginals), check=0){ - featureValues[feature_index2,i5] = i5-featureCorrection - } + featureValues[feature_index2,1:ncol(colMarginals)] = t(seq(1,ncol(colMarginals)) - featureCorrection); }else{ # label is scale, feature is categorical tests[feature_index2,1] = 2 [pVal, frequencies, means, variances] = bivar_sc(labels, feature) stats[feature_index2,1] = pVal featureCounts[feature_index2,1:nrow(frequencies)] = t(frequencies) - parfor(i6 in 1:nrow(frequencies), check=0){ - featureValues[feature_index2,i6] = i6 - featureCorrection - } + featureValues[feature_index2,1:nrow(frequencies)] = t(seq(1,nrow(frequencies)) - featureCorrection) featureMeans[feature_index2,1:nrow(means)] = t(means) featureSTDs[feature_index2,1:nrow(variances)] = t(sqrt(variances)) } http://git-wip-us.apache.org/repos/asf/systemml/blob/c170374e/src/test_suites/java/org/apache/sysml/test/integration/functions/codegen/ZPackageSuite.java ---------------------------------------------------------------------- diff --git a/src/test_suites/java/org/apache/sysml/test/integration/functions/codegen/ZPackageSuite.java b/src/test_suites/java/org/apache/sysml/test/integration/functions/codegen/ZPackageSuite.java index a9310b3..3b24fcc 100644 --- a/src/test_suites/java/org/apache/sysml/test/integration/functions/codegen/ZPackageSuite.java +++ b/src/test_suites/java/org/apache/sysml/test/integration/functions/codegen/ZPackageSuite.java @@ -26,10 +26,12 @@ import org.junit.runners.Suite; * won't run two of them at once. */ @RunWith(Suite.class) @Suite.SuiteClasses({ + AlgorithmARIMA.class, AlgorithmGLM.class, AlgorithmKMeans.class, AlgorithmL2SVM.class, AlgorithmLinregCG.class, + AlgorithmMDABivar.class, AlgorithmMLogreg.class, AlgorithmMSVM.class, AlgorithmPNMF.class,