Tutorials › Pharmacometric Workflows and Reproducible Modeling › Chunking Simulations Without Changing Results

Simulation Pipelines · Tutorial 263 of 399

Chunking Simulations Without Changing Results

Learn to chunk large simulations while preserving replicate identity, random-number assignment, and correctly pooled estimates, and to verify results against a single-batch calculation.

Advanced 12 min read

What You'll Learn

  • Define when chunking is equivalent to running all simulation replicates in one batch.
  • Preserve stable replicate identifiers and the intended random-number sequence across chunks.
  • Pool unequal chunks correctly for means and proportions.
  • Diagnose duplicated, omitted, or misassigned replicates using counts and identifiers.
  • Compare chunked and single-batch outputs while allowing for floating-point rounding.
  • Distinguish a guarantee of matching estimates from a coincidence in aggregate values.

Why Chunk a Simulation?

A pharmacometric simulation can generate more virtual patients, replicate profiles, or scenario outputs than fit comfortably in memory at once. Chunking divides the planned work into smaller batches, processes each batch, and then combines the results. It can reduce peak memory use and make long jobs easier to manage. But chunking should be a change in how much work is held at once, not an unplanned change in which virtual patients are simulated or how their random draws are assigned.

The central question is therefore not whether each batch runs successfully. It is whether the chunked run represents the same planned set of replicates and uses the same calculation as a single-batch run. Exact replicate-level agreement is possible when the inputs, random variates, model calculations, and processing order are held consistent. An aggregate estimate can still match by coincidence even when replicate-level outputs differ, so agreement of one summary alone is not proof that the simulation was preserved.

Definition: A chunk is a subset of the planned simulation replicates processed together. Chunking without changing results means that every planned replicate is represented exactly once, its inputs and random variates are assigned according to the same sampling design, and the final calculation combines all replicate outputs using the intended rule. When each replicate receives the same inputs and random variates as in the single-batch run, and the model calculation is deterministic and chunk-independent, its replicate-level result is unchanged.

Conditions for Equivalent Chunked Processing

Suppose a simulation plans \(N\) replicates, indexed by a stable identifier \(i\in\{1,\ldots,N\}\). Let \(Y_i\) be the output for replicate \(i\), such as an individual exposure metric or an indicator of whether a target was attained. A chunking scheme partitions the identifiers into disjoint sets \(C_1,\ldots,C_K\). For complete coverage, every planned identifier must belong to exactly one set:

$$ \bigcup_{k=1}^{K} C_k = \{1,\ldots,N\}, \qquad C_j\cap C_k=\varnothing \quad (j\ne k). $$

These conditions prevent omissions and duplication. The chunk size may vary, including a smaller final chunk, as long as the partition still covers the planned identifiers once each. A chunk-local row number is not a stable replicate identifier: row 1 in several chunks refers to several different replicates. Store the global identifier alongside each output so records can be checked, sorted, and joined unambiguously.

The sampling logic must also be invariant to the partition. For example, if the single-batch run assigns a particular covariate draw and random effect to replicate 17, the chunked run must not silently assign a draw intended for another replicate. A sequential random-number stream can support this when draws are consumed in the same global order, with each draw mapped to the same replicate and variable. Indexed or otherwise reproducibly assigned streams can also support it. The necessary design depends on the random-number approach; merely using the same initial seed does not ensure equivalence if chunk processing changes draw order or restarts the generator for every chunk.

Finally, the model calculation must not depend on which other replicates happen to be in the same chunk. A calculation performed independently for each virtual patient usually has this property. A calculation that estimates a shared quantity from the current batch and then uses it to transform each replicate may not: changing batch membership could change the result. Chunking is equivalent only when the calculation is separable across replicates or when any shared calculation is defined and applied consistently across the full planned simulation.

Key result: If the chunks form a disjoint, complete partition; each replicate receives the same inputs and random variates as in the single-batch design; and the per-replicate calculation is deterministic and chunk-independent, then each \(Y_i\) is the same in both runs. Consequently, applying the same aggregate calculation to all \(N\) outputs gives the same aggregate, apart from possible floating-point rounding in numerical summation.

Why Correct Pooling Matters

When an aggregate is a mean, calculate it from all replicate values or from chunk means weighted by their chunk sizes. If chunk \(k\) contains \(n_k\) outputs with mean \(\bar{Y}_k\), then \(N=\sum_{k=1}^K n_k\), and the overall mean is:

$$ \bar{Y} = \frac{\sum_{i=1}^{N}Y_i}{N} = \frac{\sum_{k=1}^{K}n_k\bar{Y}_k}{\sum_{k=1}^{K}n_k}. $$

This follows because \(n_k\bar{Y}_k\) is the sum of the outputs in chunk \(k\). Adding those chunk sums gives the sum over the full partition, and dividing by the total number of outputs gives the full-simulation mean. An unweighted average of chunk means is generally different when chunk sizes differ. The same principle applies to proportions: pool the number of events and the number of replicates, then divide, rather than averaging chunk proportions without weights.

Worked Example: Pooling Unequal Chunks for a Mean

A hypothetical simulation produces an exposure metric in hours for 10 replicates. The outputs, ordered by stable replicate identifier, are \(1.2, 1.5, 0.9, 1.4, 1.0, 1.3, 0.8, 1.6, 1.1,\) and \(1.2\). They are processed in chunks of 4, 4, and 2 replicates.

The chunk sums are \(1.2+1.5+0.9+1.4=5.0\), \(1.0+1.3+0.8+1.6=4.7\), and \(1.1+1.2=2.3\) hours. The overall mean is therefore:

$$ \bar{Y} = \frac{5.0+4.7+2.3}{4+4+2} = \frac{12.0}{10} = 1.20\ \text{hours}. $$

The chunk means are \(5.0/4=1.25\), \(4.7/4=1.175\), and \(2.3/2=1.15\) hours. Their unweighted average is \((1.25+1.175+1.15)/3=1.1917\) hours, which is not the full-simulation mean. Weighting by chunk size gives \((4(1.25)+4(1.175)+2(1.15))/10=1.20\) hours, as required.

Worked Examples of Preserving the Simulation

Worked Example: Mapping Random Draws to Stable Replicate IDs

Consider a hypothetical simulation of six virtual patients. For illustration, the covariate is calculated as \(X_i=10+2Z_i\), where \(Z_i\) is a standard normal draw assigned to replicate \(i\). A single-batch run uses the ordered draws \(-1.0, 0.5, 1.2, -0.3, 0.8,\) and \(-1.4\).

Replicate ID\(Z_i\)\(X_i=10+2Z_i\)
1-1.08.0
20.511.0
31.212.4
4-0.39.4
50.811.6
6-1.47.2

With chunks \(\{1,2\}\), \(\{3,4\}\), and \(\{5,6\}\), preserving the global mapping gives the same six covariates. For example, replicate 5 must receive \(Z_5=0.8\), so its covariate remains \(10+2(0.8)=11.6\). If a sequential generator is restarted from the same seed at the start of every two-replicate chunk, the first two draws may be repeated in each chunk. In that case the covariates would be \(8.0,11.0\) in all three chunks, rather than the single-batch values. The replicate IDs would still look complete, but their draws would be wrong. Stable identifiers must therefore be paired with a draw-allocation strategy that preserves the intended mapping.

Worked Example: Chunked and Single-Batch Proportions

A hypothetical run simulates 11 virtual patients and records whether each reaches a specified exposure target. Suppose the three chunks contain 2 successes among 4 patients, 3 among 4, and 1 among 3. The full-simulation estimated proportion is obtained by pooling the counts:

$$ \hat{p} = \frac{2+3+1}{4+4+3} = \frac{6}{11} = 0.5455. $$

The chunk proportions are \(2/4=0.5000\), \(3/4=0.7500\), and \(1/3=0.3333\). Their unweighted average is \((0.5000+0.7500+0.3333)/3=0.5278\), not the pooled estimate. Weighting them by their denominators recovers the correct result:

$$ \frac{4(0.5000)+4(0.7500)+3(0.3333)}{11} \approx \frac{6}{11} = 0.5455. $$

Thus, when the patient-level indicators are the same in both runs, the single-batch and correctly pooled chunked estimates agree. Averaging the chunk proportions equally would instead estimate an average of three chunk-level proportions, which is a different quantity when the chunk sizes differ.

Verification, Diagnostics, and Limitations

A useful comparison checks more than the final mean. Before a large run, process a small hypothetical or test simulation both as one batch and with several chunk sizes. Compare the planned and observed number of replicates, the set of IDs, selected replicate-level inputs and outputs, and the final aggregate. Exact equality is appropriate for deterministic calculations using identical inputs and arithmetic. Very small numerical differences can arise when floating-point sums are accumulated in a different order; report a tolerance appropriate to the scale and precision of the calculation rather than treating every last-bit difference as a sampling change.

Useful checks include verifying that the total output count is \(N\), that each ID occurs once, and that the smallest and largest IDs agree with the planned range. Counts alone cannot detect every error: one duplicated ID and one omitted ID can leave the total count unchanged. Comparing the actual ID set, and checking duplicates explicitly, is stronger. For an aggregate, compare the overall pooled result with a direct calculation on a saved test set of replicate outputs.

  • Repeated outputs by chunk position: may indicate that the random generator was restarted for each chunk or that chunk-local indices were mistaken for global IDs.
  • Missing or repeated IDs: indicate a partition, filtering, or output-assembly error, even if the total row count appears plausible.
  • Aggregate changes when chunk size changes: can indicate altered random-draw assignment, a chunk-dependent calculation, incomplete outputs, or incorrect weighting.
  • Small differences in a summed result: may reflect floating-point summation order; investigate whether replicate-level outputs and counts otherwise agree.

An important limitation is that matching replicate-level values is a sufficient guarantee of matching an aggregate when the same correct pooling calculation is applied; it is not a necessary condition. Different replicate values can coincidentally yield the same mean or proportion. Conversely, matching a single aggregate does not establish that identifiers, draws, or individual predictions were preserved. The strength of the verification should match the purpose of the simulation: a summary-only check is weaker than checks of the replicate set and its calculations.

Compared with a single-batch run, chunking trades some simplicity for lower memory demand and often easier recovery of partial work. A single batch avoids combining chunk summaries, but may exceed available resources. Chunking is safe when the partition, draw assignment, and aggregation are explicit. It is not a different sampling method by itself; changing the number of replicates, resampling separately within chunks, or restarting streams in a way that changes assignments changes the simulation design rather than merely its execution.

1
Define the planned replicate set.
Choose \(N\) and assign each planned replicate a stable global ID before dividing the work.
2
Specify the draw assignment.
Ensure that covariates, random effects, and residual draws map to the same replicate and variable regardless of chunk boundaries.
3
Process a complete partition.
Run each ID in exactly one chunk, retain its ID in the output, and avoid calculations whose definition changes with batch membership.
4
Pool and verify.
Combine replicate-level results or use size-weighted chunk summaries, then check IDs, counts, and agreement with a single-batch test.

Common Mistakes

  • Giving every chunk local IDs starting at 1. These labels collide across chunks. Use a global replicate ID that remains unchanged through simulation and aggregation.
  • Assuming the same seed always gives the same replicate draws. Draw order and generator restarts matter. Confirm the mapping from random variates to replicates, not just the seed value.
  • Averaging unequal chunk means or proportions equally. Weight each summary by its denominator, or pool the underlying sums and counts directly.
  • Treating agreement in one aggregate as proof of equivalence. Different replicate-level results can produce the same aggregate by coincidence. Check identifiers and replicate-level outputs when equivalence matters.
Key takeaway: Chunking preserves a simulation when it changes the processing partition but not the planned replicates, their sampling assignments, or the definition of the calculation. Keep global IDs, verify complete nonoverlapping coverage, and pool summaries with the correct denominators.

Check Your Understanding

Answer each question, then compare with the solutions below.

  1. A simulation has 23 planned replicates, processed in chunks of 10, 10, and 3. What conditions must the ID sets satisfy?
  2. Two chunks have means of 4.0 and 7.0 units, with 5 and 15 replicates, respectively. Calculate the pooled mean and the unweighted mean of the chunk means.
  3. Why can restarting a random-number generator from the same seed at every chunk change the simulation?
  4. Does an identical aggregate mean prove that two runs have identical replicate-level values? Explain.
  5. In a chunked run, the total output count equals the planned number, but some IDs may be duplicated. Name a check that can detect this problem.

Solutions. (1) The three ID sets must be disjoint and their union must be all planned IDs, \(\{1,\ldots,23\}\); each ID occurs exactly once. (2) The pooled mean is \((5(4.0)+15(7.0))/20=(20+105)/20=6.25\) units. The unweighted chunk mean is \((4.0+7.0)/2=5.50\) units, which is inappropriate because the chunk sizes differ. (3) Restarting can repeat the beginning of the random sequence in each chunk, assigning draws differently from the single-batch run. (4) No. Different replicate values can coincidentally yield the same aggregate, so replicate-level agreement is sufficient for the same correctly computed aggregate but is not necessary. (5) Compare the actual ID set with the planned set and check that each ID occurs exactly once; a count alone cannot reveal a duplicate paired with an omission.

Clinical Biostats