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.
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:
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.
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:
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:
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.0 | 8.0 |
| 2 | 0.5 | 11.0 |
| 3 | 1.2 | 12.4 |
| 4 | -0.3 | 9.4 |
| 5 | 0.8 | 11.6 |
| 6 | -1.4 | 7.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:
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:
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.
Choose \(N\) and assign each planned replicate a stable global ID before dividing the work.
Ensure that covariates, random effects, and residual draws map to the same replicate and variable regardless of chunk boundaries.
Run each ID in exactly one chunk, retain its ID in the output, and avoid calculations whose definition changes with batch membership.
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.
Check Your Understanding
Answer each question, then compare with the solutions below.
- A simulation has 23 planned replicates, processed in chunks of 10, 10, and 3. What conditions must the ID sets satisfy?
- 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.
- Why can restarting a random-number generator from the same seed at every chunk change the simulation?
- Does an identical aggregate mean prove that two runs have identical replicate-level values? Explain.
- 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.