docs: private void trainStep(DataSet dataSet, boolean parallel)
      {
          boolean autoLearners = isAutoFeatureSample();//We will need to set it back after, so remember if we need to
          if(autoLearners)
              baseLearner.setRandomFeatureCount(Math.max((int)Math.sqrt(dataSet.getNumFeatures()), 1));
          else
              baseLearner.setRandomFeatureCount(featureSamples);
          
          int roundsToDistribut = maxForestSize;
          int roundShare = roundsToDistribut / SystemInfo.LogicalCores;//The number of rounds each thread gets
          int extraRounds = roundsToDistribut % SystemInfo.LogicalCores;//The number of extra rounds that need to get distributed
                  
          if(!parallel)//No point in duplicatin recources
              roundShare = roundsToDistribut;//All the rounds get shoved onto one thread
          ExecutorService threadPool = parallel ? ParallelUtils.CACHED_THREAD_POOL : new FakeExecutor();
          
          //Random used for creating more random objects, faster to duplicate such a small recourse then share and lock
          Random rand = RandomUtil.getRandom();
          List<Future<LearningWorker>> futures = new ArrayList<>(SystemInfo.LogicalCores);
          
          int[][] counts = null;
          AtomicDoubleArray pred = null;
          if(dataSet instanceof RegressionDataSet)
          {
              pred = new AtomicDoubleArray(dataSet.size());
              counts = new int[pred.length()][1];//how many predictions are in this?
          }
          else
          {
              counts = new int[dataSet.size()][((ClassificationDataSet)dataSet).getClassSize()];
          }
  
          while (roundsToDistribut > 0)
          {
              int extra = (extraRounds-- > 0) ? 1 : 0;
              Future<LearningWorker> future = threadPool.submit(new LearningWorker(dataSet, roundShare + extra, new Random(rand.nextInt()), counts, pred));
              roundsToDistribut -= (roundShare + extra);
              futures.add(future);
          }
  
  
          
          outOfBagError = 0;
          try
          {
              List<LearningWorker> workers = ListUtils.collectFutures(futures);
              for (LearningWorker worker : workers)
                  forest.addAll(worker.learned);
              
              if (useOutOfBagError)
              {
                  if (dataSet instanceof ClassificationDataSet)
                  {
                      ClassificationDataSet cds = (ClassificationDataSet) dataSet;
                      for (int i = 0; i < counts.length; i++)
                      {
                          int max = 0;
                          for (int j = 1; j < counts[i].length; j++)
                          if(counts[i][j] > counts[i][max])
  
                              max = j;
                          if(max != cds.getDataPointCategory(i))
                              outOfBagError++;
                      }
                  }
                  else
                  {
                      RegressionDataSet rds = (RegressionDataSet) dataSet;
                      for (int i = 0; i < counts.length; i++)
                          outOfBagError += Math.pow(pred.get(i)/counts[i][0]-rds.getTargetValue(i), 2);
                  }
                  outOfBagError /= dataSet.size();
              }
              
              if(useOutOfBagImportance)//collect feature importance stats from each worker
              {
                  feature_importance = new OnLineStatistics[dataSet.getNumFeatures()];
                  for(int j = 0; j < dataSet.getNumFeatures(); j++)
                      feature_importance[j] = new OnLineStatistics();
                  
                  for(LearningWorker worker : workers)
                      for(int j = 0; j < dataSet.getNumFeatures(); j++)
                          feature_importance[j].add(worker.fi[j]);
                      
              }
          }
          catch (Exception ex)
          {
              Logger.getLogger(RandomForest.class.getName()).log(Level.SEVERE, null, ex);
          }
          
          
  
      }