/** * Copyright (C) 2001-2017 by RapidMiner and the contributors * * Complete list of developers available at our web site: * * http://rapidminer.com * * This program is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero General Public License as published by the Free Software Foundation, either version 3 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with this program. * If not, see http://www.gnu.org/licenses/. */ package com.rapidminer.operator.concurrency.internal; import java.util.ArrayList; import java.util.List; import com.rapidminer.example.ExampleSet; import com.rapidminer.example.utils.ExampleSets; import com.rapidminer.operator.ExecutionUnit; import com.rapidminer.operator.IOObject; import com.rapidminer.operator.Operator; import com.rapidminer.operator.OperatorChain; import com.rapidminer.operator.OperatorDescription; import com.rapidminer.parameter.ParameterType; import com.rapidminer.parameter.ParameterTypeBoolean; import com.rapidminer.parameter.UndefinedParameterError; /** * This is an abstract class for all Operators that have subprocesses that should be executed in * parallel. * * @author Sebastian Land * @since 7.4 * */ public abstract class ParallelOperatorChain extends OperatorChain { private static String PARAMETER_ENABLE_PARALLEL_EXECUTION = "enable_parallel_execution"; public ParallelOperatorChain(OperatorDescription description, String... subprocessNames) { super(description, subprocessNames); } /** * This method checks whether the user has disabled the parallel execution or whether there are * breakpoints inside the subprocess. In boths situations the process needs to be executed * synchronously. * * @return */ protected boolean checkParallelizability() { boolean executeParallely = getParameterAsBoolean(PARAMETER_ENABLE_PARALLEL_EXECUTION); if (executeParallely) { // now check if there's a break point. Then we switch back to serial as well. for (ExecutionUnit unit : getSubprocesses()) { for (Operator operator : unit.getAllInnerOperators()) { if (operator.isEnabled() && operator.hasBreakpoint()) { return false; } } } } return executeParallely; } /** * This method returns a List of the copies or clones of each IOObject. Copies are simply * references on the same objects if the object is immutable. ExampleSets are provided by cloned * reference or materialized, depending on parameter. * * @param inputData * @param materializeIfPossible * if {@code true}, {@link ExampleSet}s will be materialized instead of cloned * @return * @throws UndefinedParameterError */ @SuppressWarnings("unchecked") protected <T extends IOObject> List<T> getDataCopy(List<IOObject> inputData, boolean materializeIfPossible) throws UndefinedParameterError { List<IOObject> clonedInputData = new ArrayList<>(inputData.size()); for (IOObject object : inputData) { clonedInputData.add(getDataCopy(object, materializeIfPossible)); } return (List<T>) clonedInputData; } /** * This method returns a copy or clone of the given {@link IOObject}. Copies are simply * references on the same objects if the object is immutable. For ExampleSets the behavior * depends on the second parameter. If requested, ExampleSets are checked for their * thread-safety and materialized if necessary. * * @param inputData * @param materializeUnsafeExampleSets * if {@code true}, ExampleSets that are not thread-safe are materialized * @return * @throws UndefinedParameterError */ @SuppressWarnings("unchecked") protected <T extends IOObject> T getDataCopy(IOObject input, boolean materializeUnsafeExampleSets) throws UndefinedParameterError { if (materializeUnsafeExampleSets && input instanceof ExampleSet) { ExampleSet set = (ExampleSet) input; return (T) ExampleSets.createThreadSafeCopy(set); } else { if (input != null) { return (T) input.copy(); } return null; } } @Override public List<ParameterType> getParameterTypes() { List<ParameterType> types = super.getParameterTypes(); types.add(new ParameterTypeBoolean(PARAMETER_ENABLE_PARALLEL_EXECUTION, "This parameter enables the parallel execution of this operator. Please disable the parallel execution if you run into memory problems.", true, true)); return types; } }