【java】jmetal中运行线程数的设置

jmetal中没有自带统计算法运行时间的程序,因此,为了记录算法的运行时间,需要将其设置为单线程的方式运行,在jemtal中,可以通过ExperimentBuilder对象的setNumberOfCores方法设置。

如上图所示,通过将内核数设置为0, 实现了程序的单线程方式运行。

package org.uma.jmetal.util.experiment.util;

import java.io.File;
import java.util.List;

import org.uma.jmetal.algorithm.Algorithm;
import org.uma.jmetal.solution.Solution;
import org.uma.jmetal.util.JMetalLogger;
import org.uma.jmetal.util.experiment.Experiment;
import org.uma.jmetal.util.fileoutput.SolutionListOutput;
import org.uma.jmetal.util.fileoutput.impl.DefaultFileOutputContext;

import com.sim.common.MathUtil;

/**
 * Class defining tasks for the execution of algorithms in parallel.
 *
 * @author Antonio J. Nebro <[email protected]>
 */
public class ExperimentAlgorithm<S extends Solution<?>, Result extends List<S>> {
	private Algorithm<Result> algorithm;
	private String algorithmTag;
	private String problemTag;
	private String referenceParetoFront;
	private int runId;
    //添加
	private double runTime;

	/**
	 * Constructor
	 */
	public ExperimentAlgorithm(Algorithm<Result> algorithm, String algorithmTag, ExperimentProblem<S> problem,
			int runId) {
		this.algorithm = algorithm;
		this.algorithmTag = algorithmTag;
		this.problemTag = problem.getTag();
		this.referenceParetoFront = problem.getReferenceFront();
		this.runId = runId;
	}

	public ExperimentAlgorithm(Algorithm<Result> algorithm, ExperimentProblem<S> problem, int runId) {
		this(algorithm, algorithm.getName(), problem, runId);
	}

	public void runAlgorithm(Experiment<?, ?> experimentData) {
		String outputDirectoryName = experimentData.getExperimentBaseDirectory() + "/data/" + algorithmTag + "/"
				+ problemTag;

		File outputDirectory = new File(outputDirectoryName);
		if (!outputDirectory.exists()) {
			boolean result = new File(outputDirectoryName).mkdirs();
			if (result) {
				JMetalLogger.logger.info("Creating " + outputDirectoryName);
			} else {
				JMetalLogger.logger.severe("Creating " + outputDirectoryName + " failed");
			}
		}

		String funFile = outputDirectoryName + "/FUN" + runId + ".tsv";
		String varFile = outputDirectoryName + "/VAR" + runId + ".tsv";
		JMetalLogger.logger.info(" Running algorithm: " + algorithmTag + ", problem: " + problemTag + ", run: " + runId
				+ ", funFile: " + funFile);

		// 1.记录开始时间
		long startTime = System.currentTimeMillis();
		// 2.运行算法
		algorithm.run();
		// 3.记录结束时间
		long endTime = System.currentTimeMillis();
		// 4.计算耗时
		runTime = MathUtil.round(MathUtil.divide(endTime - startTime, 1000), 2);
		JMetalLogger.logger.info("No." + runId + " " + algorithmTag + " on " + problemTag + " speed: " + runTime + "s");

		Result population = algorithm.getResult();

		// 这里就是为什么var和fun文件始终位/t分割的原因
		new SolutionListOutput(population).setSeparator("\t")
				.setVarFileOutputContext(new DefaultFileOutputContext(varFile))
				.setFunFileOutputContext(new DefaultFileOutputContext(funFile)).print();
	}

	public Algorithm<Result> getAlgorithm() {
		return algorithm;
	}

	public String getAlgorithmTag() {
		return algorithmTag;
	}

	public String getProblemTag() {
		return problemTag;
	}

	public String getReferenceParetoFront() {
		return referenceParetoFront;
	}

	public int getRunId() {
		return this.runId;
	}

	public double getRunTime() {
		return runTime;
	}
}

那么,为什么jmetal中内核数设为0就可以使得其单线程运行呢?

答案在于:jmetal的多线程实现方式是使用JDK8的并行流,而并行流中通过设置如下的全局属性限制线程池的大小:

System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism","0");

 官方的JDK给出的解释如下:

上图也解释了为什么我们将并行等级设置为0时,jmetal仍然可以执行算法的原因,因为ForkJoinPool的源码实现中定义了至少有一个活动线程。经笔者实验,将内核数【并行等级】设为1时,运行的线程数为2;当内核数【并行等级】设为2时,运行的线程数为3,这里运行的线程数是指实际执行算法的线程个数。下图清晰地展示了并行等级设置为2时的情况下,线程的个数:

发布了192 篇原创文章 · 获赞 318 · 访问量 28万+

猜你喜欢

转载自blog.csdn.net/zyxhangiian123456789/article/details/100939331