@Override
 protected T compute() {
   T currentBest = initial;
   for (int step = 0; step < steps; step++) {
     logger.log(
         Level.INFO,
         "On iteration step {0}, current best has score {1}",
         new Object[] {step, scorer.score(currentBest)});
     double temp = primaryTempFun.temperature(step, steps);
     ForkJoinTask<T> task = new ParallelOptimizationStep(currentBest, temp);
     stopwatch.start();
     currentBest = task.invoke();
     stopwatch.stop();
     logger.log(
         Level.INFO,
         "Iteration step {0} took {1}ms wall clock time",
         new Object[] {step, stopwatch.elapsedMillis()});
   }
   return currentBest;
 }
 @Override
 protected T compute() {
   long start = System.currentTimeMillis();
   long dur = duration.getMillis();
   long lastUpdate = start;
   int step;
   T currentBest = initial;
   Csv.Builder builder = Csv.newBuilder();
   long totalTime = 0;
   for (step = 0; System.currentTimeMillis() - start < dur; step++) {
     logger.log(
         Level.INFO,
         "On iteration step {0}, current best has score {1}",
         new Object[] {step, scorer.score(currentBest)});
     double temp =
         primaryTempFun.temperature((int) (System.currentTimeMillis() - start), (int) dur);
     ForkJoinTask<T> task = new ParallelOptimizationStep(currentBest, temp);
     stopwatch.start();
     currentBest = task.invoke();
     stopwatch.stop();
     if (step % 20 == 0) {
       builder.add(
           Csv.newRowBuilder()
               .add("%d", System.currentTimeMillis() - start)
               .add("%8.3f", scorer.score(currentBest))
               .build());
     }
     logger.log(
         Level.FINE,
         "Iteration {0} took {1} of wall clock time",
         new Object[] {
           step,
           Converters.PERIOD_FORMATTER.print(Period.millis((int) stopwatch.elapsedMillis()))
         });
     totalTime += stopwatch.elapsedMillis();
     logger.log(
         Level.FINER,
         "Average step time: {0}",
         new Object[] {
           Converters.PERIOD_FORMATTER.print(Period.millis((int) (totalTime / (step + 1))))
         });
     stopwatch.reset();
     if ((System.currentTimeMillis() - lastUpdate) > noProgressCancel.getMillis()) {
       logger.log(Level.INFO, "Cutting off optimization for lack of progress");
       break;
     }
   }
   if (step != 0) {
     logger.log(
         Level.INFO,
         "Average optimizer iteration took {0}",
         Duration.millis((long) (System.currentTimeMillis() - start) / step)
             .toPeriod()
             .toString(Converters.PERIOD_FORMATTER));
   }
   try {
     Files.write(builder.build().toString(), new File("optimization-log.csv"), Charsets.UTF_8);
   } catch (IOException e) {
     logger.throwing("ConcurrentOptimizer", "log", e);
   }
   return currentBest;
 }