You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat: add opt-in multithreaded fill to synthetic data generators
The synthetic generators are dominated by single-threaded numpy
standard_normal draws (~0.9 GB/s), leaving cores idle. Add an opt-in
n_workers parameter to scan_synthetic_regression and scan_synthetic_panel
that fills the x/eps Gaussian draws in parallel.
Draws are generated in fixed-size blocks (n_workers * fetch_size rows),
each split across worker threads that fill disjoint slices in place via
out=. standard_normal releases the GIL, so the fill scales across cores
(~3x for regression, universe-dependent for panels). Reproducibility is
re-keyed to (seed, n_workers, fetch_size) and stays independent of the
batch_size Polars picks, so is_pure remains sound. n_workers=1 (default)
keeps the exact serial path and its byte-for-byte output.
Per-worker seed sub-streams are spawned lazily per block to keep seed
storage at O(n_workers) and preserve bounded, streaming memory.
Signed-off-by: Pascal Tomecek <40371786+ptomecek@users.noreply.github.com>
chunk_key: If provided together with ``n_chunks``, emits a monotonic ``Int64`` column with this name whose values are ``0, 1, ..., n_chunks - 1``. Must not collide with a generated column name.
192
242
n_chunks: Number of contiguous chunks to split ``n_samples`` into. Required when ``chunk_key`` is set. Must satisfy ``1 <= n_chunks <= n_samples``.
193
243
seed: Seed for ``np.random.default_rng``. If None, uses fresh entropy per call (and the source is registered with ``is_pure=False``).
244
+
n_workers: Number of threads used to fill the ``x``/``y`` Gaussian draws (the dominant cost) in parallel. ``1`` (default) keeps the fully serial path and its exact output. With ``n_workers > 1`` the draws are generated in fixed-size blocks split across threads, so reproducibility is keyed on ``(seed, n_workers, fetch_size)`` and remains independent of the ``batch_size`` Polars chooses; values differ from the serial path. Peak generation memory grows with ``n_workers`` (a block holds ``n_workers * fetch_size`` rows). Most useful when ``n_samples`` is large.
194
245
fetch_size: Default number of rows generated per batch when Polars does not provide a ``batch_size``. Must be >= 1. Defaults to 10_000.
195
246
description: Optional free-form description of this source instance, attached to its OpenTelemetry span (``explain_detail``).
196
247
"""
@@ -260,6 +311,7 @@ def mean_computer(
260
311
mean_computer=mean_computer,
261
312
extras_schema=extras_schema,
262
313
chunk_sizes=chunk_sizes,
314
+
n_workers=n_workers,
263
315
explain_name="scan_synthetic_regression",
264
316
explain_detail=description,
265
317
)
@@ -282,6 +334,7 @@ def scan_synthetic_panel(
282
334
epsilon_loc: float=0.0,
283
335
epsilon_scale: float=1.0,
284
336
seed: int|None=None,
337
+
n_workers: int=1,
285
338
fetch_size: int=10_000,
286
339
description: str|None=None,
287
340
) ->pl.LazyFrame:
@@ -310,6 +363,7 @@ def scan_synthetic_panel(
310
363
epsilon_loc: Mean of the Gaussian noise. Defaults to 0.0.
311
364
epsilon_scale: When ``use_weights=False``, the noise stddev for every row. When ``use_weights=True``, the *reference* stddev at ``w=1``; actual per-row noise is ``N(loc, (epsilon_scale/√w)²)``. Must be >= 0. Defaults to 1.0.
312
365
seed: Seed for ``np.random.default_rng``. If None, uses fresh entropy per call (and the source is registered with ``is_pure=False``).
366
+
n_workers: Number of threads used to fill the ``x``/``y`` Gaussian draws (the dominant cost) in parallel. ``1`` (default) keeps the fully serial path and its exact output. With ``n_workers > 1`` the draws are generated in fixed-size blocks split across threads, so reproducibility is keyed on ``(seed, n_workers, fetch_size)`` and remains independent of the ``batch_size`` Polars chooses; values differ from the serial path. Peak generation memory grows with ``n_workers`` (a block holds ``n_workers * fetch_size`` rows). For panels the per-date batch is ``n_symbols`` rows, so parallelism only helps when ``n_symbols`` is large.
313
367
fetch_size: Default number of rows generated per batch when Polars does not provide a ``batch_size``. Must be >= 1. Defaults to 10_000.
314
368
description: Optional free-form description of this source instance, attached to its OpenTelemetry span (``explain_detail``).
0 commit comments