Source:
<code>public void run(final int iteration) { LOG.log(Level.INFO, "Iteration Started"); final Map<Long, Document> workloadMap = memoryStore.getAll(); final List<Document> workload = new ArrayList<>(workloadMap.values()); final int numTotalDocuments = workload.size(); int numDocumentsSampled = 0; int numDocumentsToSample = miniBatchSize; final int numMiniBatches = (int) Math.ceil((double) numTotalDocuments / miniBatchSize); <START> final int numRemainingForLastMiniBatch = numTotalDocuments % miniBatchSize; <END> LOG.log(Level.INFO, "Number of mini-batches for epoch {0} = {1}", new Object[] {iteration, numMiniBatches}); for (int miniBatchIdx = 0; miniBatchIdx < numMiniBatches; miniBatchIdx++) { if (miniBatchIdx == numMiniBatches - 1) { numDocumentsToSample = (numRemainingForLastMiniBatch == 0) ? miniBatchSize : numRemainingForLastMiniBatch; } sampler.sample(workload.subList(numDocumentsSampled, numDocumentsSampled + numDocumentsToSample)); numDocumentsSampled += numDocumentsToSample; LOG.log(Level.INFO, "{0} documents out of {1} have been sampled", new Object[]{numDocumentsSampled, numTotalDocuments}); } LOG.log(Level.INFO, "Start computing log likelihood"); final List<int[]> wordTopicCounts = parameterWorker.pull(vocabList); final int[] wordTopicCountsSummary = wordTopicCounts.remove(numVocabs); LOG.log(Level.INFO, "App metric log: {0}", buildAppMetrics(statCalculator.computeDocLLH(workload), statCalculator.computeWordLLH(wordTopicCounts, wordTopicCountsSummary))); LOG.log(Level.INFO, "Iteration Ended"); }</code><technical_language>@gyeongin Good question. I agree case is efficient, complexity increased more if consider reconfiguration in EM. @jooykim, @mhkwon924 I decided tackle issue later</technical_language>

Target:
public void run(final int iteration) { final long iterationBeginMs = System.currentTimeMillis(); resetTracers(); final Map<Long, Document> workloadMap = memoryStore.getAll(); final List<Document> workload = new ArrayList<>(workloadMap.values()); final int numEMBlocks = memoryStore.getNumBlocks(); final int numTotalDocuments = workload.size(); int numDocumentsSampled = 0; int numDocumentsToSample = miniBatchSize; final int numMiniBatches = (int) Math.ceil((double) numTotalDocuments / miniBatchSize); final int remainderForLastMiniBatch = numTotalDocuments % miniBatchSize; final int numInstancesForLastMiniBatch = remainderForLastMiniBatch == 0 ? miniBatchSize : remainderForLastMiniBatch; LOG.log(Level.INFO, "Number of mini-batches for epoch {0} = {1}", new Object[] {iteration, numMiniBatches}); for (int miniBatchIdx = 0; miniBatchIdx < numMiniBatches; miniBatchIdx++) { if (miniBatchIdx == numMiniBatches - 1) { numDocumentsToSample = numInstancesForLastMiniBatch; } sampler.sample(workload.subList(numDocumentsSampled, numDocumentsSampled + numDocumentsToSample), computeTracer, pushTracer, pullTracer); numDocumentsSampled += numDocumentsToSample; LOG.log(Level.INFO, "{0} documents out of {1} have been sampled", new Object[]{numDocumentsSampled, numTotalDocuments}); } final double elapsedTimeSec = (System.currentTimeMillis() - iterationBeginMs) / 1000.0D; LOG.log(Level.INFO, "Start computing log likelihood"); final List<int[]> wordTopicCounts = parameterWorker.pull(vocabList); final int[] wordTopicCountsSummary = wordTopicCounts.remove(numVocabs); final Metrics appMetrics = buildAppMetrics(statCalculator.computeDocLLH(workload), statCalculator.computeWordLLH(wordTopicCounts, wordTopicCountsSummary)); final WorkerMetrics workerMetrics = buildMetricsMsg(iteration, appMetrics, numMiniBatches, numEMBlocks, workload.size(), elapsedTimeSec); LOG.log(Level.INFO, "WorkerMetrics {0}", workerMetrics); sendMetrics(workerMetrics); }