Why Parallel Randomness Needs an Assignment Rule
A stochastic analysis may use randomness at several points: selecting cells for a diagnostic subset, drawing bootstrap samples, initializing a model, or simulating a null distribution. In a sequential script, one random-number generator can supply these draws in a fixed order. In a parallel pipeline, multiple tasks may request random numbers at the same time. If they share one mutable generator state, the order of requests can depend on scheduling, so the results can change when the worker count or execution order changes.
The relevant goal is not merely to set one starting seed. It is to make a reproducible assignment from each logical task to its own random-number stream. A logical task might be “bootstrap replicate 12 for cell type A” or “subsample cells from sample B.” Its stream should be determined by its identity, not by the worker that happens to execute it. This develops the subject of seed management and the earlier material on why a fixed seed does not guarantee reproducibility.
A pseudorandom generator is deterministic once its state is fixed: applying the same generator algorithm to the same initial state produces the same sequence. The stream assignment therefore has two distinct requirements:
- Reproducibility: the same task, inputs, generator, and assigned state produce the same random draws.
- Separation: different tasks receive streams designed not to repeat one another’s draws or introduce problematic dependence.
Pseudorandom streams are not literally independent random variables in the mathematical sense. Independence is a property of probability distributions; a computer generator produces deterministic values. In practice, stream-splitting methods are designed to provide streams with strong statistical properties. The strength of that design depends on the generator and the splitting method, so “use different integer seeds” is not, by itself, a universal guarantee of non-overlap or independence.
Assign Streams to Tasks, Not Workers
Suppose a pipeline has tasks \(T_1,\ldots,T_m\). Let \(K_i\) be a stable key identifying task \(T_i\), and let \(S_i\) be the generator state assigned to it. The assignment should be a deterministic function of a recorded master seed and the task key:
Here \(A\) is a documented stream allocator, such as a generator’s supported child-stream or substream mechanism. The task key should describe the work rather than its execution: for example, a replicate number, a sample identifier, and an operation name. A worker number is a poor key. If replicate 8 runs on worker 2 in one run and worker 5 in another, it should still receive the same stream.
For tasks with multiple stochastic stages, include a stable stage label or create a child stream for each stage. For example, a model-fitting task might separately assign streams to initialization and stochastic optimization. That prevents a change in the number of random draws during initialization from shifting every later draw used by optimization. The task’s inputs, cell ordering, generator family, and algorithm version also need to be controlled if identical results are expected.
The stream allocator must be selected and used according to its documented rules. A supported hierarchical splitting procedure is preferable to ad hoc arithmetic on seeds or to repeatedly seeding a generator with nearby integers. If keys are converted to seeds with a hash, use a stable, documented mapping with domain-separated keys, and recognize that a finite seed space can have collisions. A hash-based mapping is not automatically equivalent to a generator’s formal substream facility.
Worked Example: Subsampling Cells Across Workers
Suppose a hypothetical dataset contains ten cells with fixed identifiers c01 through c10. A pipeline must select four cells without replacement for a diagnostic calculation. It assigns the logical task key “diagnostic-subsample, dataset-A, version-1” a stream using the master seed 824. A documented stream allocator produces a permutation whose first four indices are 7, 2, 10, and 4.
The sampling rule is to take the first four positions from that permutation:
Thus the selected identifiers are c07, c02, c10, and c04. Each index appears once, as required for sampling without replacement. If the task is moved from one worker to another, the task key remains the same, so the same stream and the same four identifiers are used.
Now suppose the pipeline also selects cells from dataset B. It must use a different stable task key, such as “diagnostic-subsample, dataset-B, version-1,” rather than reusing dataset A’s stream. The allocator then assigns a separate stream. This does not mean the selected cell lists must have different index numbers: each dataset has its own cells and can legitimately yield overlapping positions. It means the random draws are not inadvertently copied from the same generator state.
Why Task-Specific Streams Give Schedule-Invariant Results
The key justification is that a task’s random values no longer depend on the sequence of requests made by other tasks. Let \(F_i\) denote the deterministic computation for task \(i\), including its inputs and generator algorithm. With a task-specific initial state, its result can be written as:
Reordering tasks changes when each \(F_i\) runs, but it does not change \(\text{input}_i\) or \(S_i\). Therefore, under deterministic execution of the task, its result is unchanged. In contrast, with a single shared generator, the state supplied to a task depends on which task consumed random values first. Reordering requests can then change the task’s random values and its result.
This argument assumes that the task key and its inputs are stable, that the allocator deterministically assigns the same state to the key, and that no mutable generator is shared between tasks. It also assumes that the generator and the task’s random-number consumption behave deterministically in the relevant software environment. These conditions establish schedule invariance; they do not guarantee identical floating-point results across all software versions or hardware.
Worked Example: Bootstrap Replicates With Stable Identities
Consider a hypothetical measurement of four cells, with values 2, 4, 6, and 8 units. A bootstrap replicate draws four observations with replacement and calculates their mean. Assign each replicate its own stream using a key containing the analysis name and replicate number.
Suppose the stream for replicate 1 generates the index sequence 1, 1, 3, 4. Its bootstrap sample is 2, 2, 6, 8, so its mean is:
Suppose replicate 2 generates indices 2, 2, 2, 4. Its sample is 4, 4, 4, 8, giving:
If replicate 2 finishes before replicate 1, the results remain 5.0 and 4.5 units for their respective replicate identities. If a failed replicate 1 is retried with the same key and inputs, it repeats the same draw. By contrast, if all replicates consume a shared stream, changing the order or number of draws in one replicate can shift the random values used by later replicates.
Common Failure Modes and Their Diagnostics
Parallel random-number errors can be difficult to notice because a pipeline may complete successfully and produce plausible-looking estimates. Use an explicit stream-assignment record and test the behavior of the pipeline, rather than relying only on a successful run.
- Giving every worker the same seed. Workers initialized identically can produce identical sequences. This is especially dangerous when each worker processes a different chunk: the chunks may receive repeated patterns of random choices.
- Using worker IDs as task keys. Results can change when tasks are assigned to different workers or the worker count changes. Give the random stream to the task, not to the worker.
- Sharing one mutable generator across tasks. Concurrent access can make the order of state updates depend on scheduling. Use isolated task streams rather than letting tasks draw from shared mutable state.
- Using unstable identifiers. Keys based on list position, temporary filenames, or an unordered collection can change when the pipeline is reorganized. Use canonical, persistent identifiers and a specified ordering.
- Assuming different seeds prove independence. Distinct seed values may still be a poor stream-allocation strategy for a particular generator. Check the generator documentation and use its recommended splitting approach.
- Changing task boundaries without noticing. If one task is split into several chunks, or several tasks are combined, the mapping from keys to random draws may change. Define logical task granularity deliberately and record it.
Useful diagnostics include verifying that every logical task key is unique, recording the generator family and allocator, and comparing outputs after changing task order and worker count. Inspecting initial values from each stream can reveal obvious duplication, but distinct initial values do not prove good stream separation. Likewise, passing a few schedule-invariance tests does not establish theoretical independence.
Worked Example: Detecting Duplicate Worker Streams
A hypothetical pipeline has two workers, each processing a different group of cells. A programmer initializes both worker generators with seed 314. For a particular generator, suppose each initialization produces the same first uniform values, 0.18, 0.73, and 0.41. If each worker maps these values to local cell choices in the same way, both groups may receive the same pattern of random positions.
The problem is not that the workers processed the same cells; their inputs differ. The problem is that they began from identical generator states and therefore used identical pseudorandom sequences. The correction is to assign distinct streams to the logical sampling tasks using the generator’s supported splitting procedure and stable task keys. For instance, keys might identify “group-A subsample” and “group-B subsample.” Re-running the pipeline should reproduce each group’s result, while changing which worker executes either task should have no effect.
A practical check is to run the same task set with one worker and with several workers, then compare outputs by task key. Differences indicate that some randomness may still depend on scheduling, task partitioning, or unrecorded state. Agreement is a useful diagnostic, not a proof that the streams are statistically independent.
Choosing Among Stream-Management Approaches
| Approach | Strength | Main risk or limitation |
|---|---|---|
| One shared generator | Simple for a strictly sequential computation | Parallel request order can change results; concurrent state access may be unsafe |
| One seed per worker | Separates worker initialization in some designs | Task results can depend on worker assignment or worker count; identical worker seeds duplicate sequences |
| One stream per logical task | Supports repeatable task results despite changes in scheduling | Requires stable task keys and a sound stream-splitting method |
| One stream per replicate or subtask | Allows targeted retries and limits interference between stages | Can create many streams; task granularity and allocator limits must be understood |
For cell subsampling, define a stable task key for the dataset, cell group, and sampling purpose, and keep the cell ordering canonical. For bootstrap or other resampling procedures, replicate identifiers are natural keys: replicate 1 should retain its assigned stream if more replicates are added later. Avoid defining replicate streams by taking successive portions of a shared stream when the goal is to keep existing replicates unchanged as the pipeline expands.
Task-level streams improve control, but they do not remove every source of variation. Results may still change if the input cells change order, the sampling algorithm changes, the generator implementation changes, or a task consumes a different number of random values. Record the master seed, generator and splitting method, task-key scheme, software versions, inputs, and task granularity. Cross-version bit-for-bit identity should only be expected when the relevant software explicitly guarantees it.
Check Your Understanding
Answer each question, then compare your reasoning with the solutions.
- Why can a shared generator make bootstrap results depend on the order in which parallel replicates finish?
- A pipeline uses the worker number as the key for a cell-subsampling stream. What change makes the assignment more stable?
- Four cells have values 3, 5, 7, and 9 units. A bootstrap draw uses indices 1, 3, 3, 4. Calculate its mean.
- Two workers start from the same seed and produce the same sequence. Does this establish that their streams are independent? Explain.
- Name two conditions, besides assigning streams, that are needed to reproduce a task’s result.
Solutions. (1) A shared generator advances as requests are made. If a replicate consumes values before another replicate in one run, but after it in another, the second replicate can receive a different part of the sequence. (2) Use a stable logical task key, such as the dataset and sampling purpose, so the task keeps its stream if it moves to another worker. (3) The resampled values are 3, 7, 7, and 9, so the mean is \((3+7+7+9)/4=26/4=6.5\) units. (4) No. Identical sequences indicate duplicated generator states, not independent streams; use a documented splitting method and distinct task keys. (5) Examples include unchanged inputs and cell ordering, the same generator and algorithm, and deterministic task execution in the relevant software environment.