chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 13:17:40 +08:00
commit f1825c8ceb
10096 changed files with 2364182 additions and 0 deletions
+196
View File
@@ -0,0 +1,196 @@
"""
This file tests the reproducibility of the random API with different seed configurations.
"""
import pytest
import ray
from ray.data import RandomSeedConfig
from ray.data.context import DataContext
from ray.data.tests.conftest import * # noqa
from ray.tests.conftest import * # noqa
DATASET_SIZE = 40
NUM_BLOCKS = 8
METHODS = ["random_shuffle", "random_sample", "randomize_block_order"]
@pytest.fixture
def base_dataset(ray_start_regular_shared) -> ray.data.Dataset:
"""Create a base dataset for testing."""
ctx = DataContext.get_current()
ctx.enable_progress_bars = False
return ray.data.range(DATASET_SIZE, override_num_blocks=NUM_BLOCKS)
@pytest.fixture(params=METHODS)
def method(request):
return request.param
def create_seed_config(seed_param):
"""Create seed config from parametrized values."""
if seed_param is None:
return None
if isinstance(seed_param, int):
return seed_param
if seed_param == "RandomSeedConfig_false":
return RandomSeedConfig(seed=42, reseed_after_execution=False)
if seed_param == "RandomSeedConfig_true":
return RandomSeedConfig(seed=42, reseed_after_execution=True)
raise ValueError(f"Unknown seed_param: {seed_param}")
def collect_batches_from_epochs(ds, num_epochs=3, batch_size=5):
"""Collect batches from multiple epochs of iter_batches."""
epochs = []
for _ in range(num_epochs):
epoch_data = []
for batch in ds.iter_batches(batch_size=batch_size, batch_format="pandas"):
epoch_data.extend(batch["id"].tolist())
epochs.append(epoch_data)
return epochs
def apply_random_operation(ds, method, seed, fraction=None):
"""Apply the specified random operation to the dataset."""
if method == "random_shuffle":
return ds.random_shuffle(seed=seed)
if method == "random_sample":
return ds.random_sample(fraction=fraction or 0.5, seed=seed)
if method == "randomize_block_order":
return ds.randomize_block_order(seed=seed)
raise ValueError(f"Unknown method: {method}")
def _normalize_results(method, result):
"""Sort random_sample results to ignore parallelism-induced ordering differences."""
if method == "random_sample":
return sorted(result, key=lambda x: x["id"])
return result
@pytest.mark.parametrize(
"seeds,expect_same",
[
((42, 42), True),
((42, 123), False),
],
)
def test_random_api_seed_determinism(base_dataset, method, seeds, expect_same):
"""Test that same seeds produce same results and different seeds produce different
results."""
seed1, seed2 = seeds
ds1 = apply_random_operation(base_dataset, method, seed1)
ds2 = apply_random_operation(base_dataset, method, seed2)
result1 = _normalize_results(method, ds1.take_all())
result2 = _normalize_results(method, ds2.take_all())
if expect_same:
assert result1 == result2, f"Same seed should produce same results for {method}"
else:
assert (
result1 != result2
), f"Different seeds should produce different results for {method}"
def test_random_api_none_seed(base_dataset, method):
"""Test that seed=None produces non-deterministic results.
For random_sample, results are sorted so we compare which items were
sampled rather than task completion order. For shuffle methods, ordering
*is* the randomness being tested.
"""
ds1 = apply_random_operation(base_dataset, method, None)
ds2 = apply_random_operation(base_dataset, method, None)
result1 = _normalize_results(method, ds1.take_all())
result2 = _normalize_results(method, ds2.take_all())
assert (
result1 != result2
), f"seed=None should produce non-deterministic results for {method}"
def test_random_api_reseed_behavior(base_dataset):
"""Test reseed_after_execution behavior across multiple epochs.
For shuffle/block_order we compare full row order (no sort); for random_sample
we compare sorted items so we only assert same set of sampled rows.
"""
seed_value = 42
seed_false = RandomSeedConfig(seed=seed_value, reseed_after_execution=False)
seed_true = RandomSeedConfig(seed=seed_value, reseed_after_execution=True)
# Test random_shuffle with reseed_after_execution=False
ds = base_dataset.random_shuffle(seed=seed_false)
epochs = collect_batches_from_epochs(ds, num_epochs=3, batch_size=5)
assert (
epochs[0] == epochs[1] == epochs[2]
), "reseed_after_execution=False should produce same results"
# Test random_shuffle with reseed_after_execution=True
ds = base_dataset.random_shuffle(seed=seed_true)
epochs = collect_batches_from_epochs(ds, num_epochs=3, batch_size=5)
assert (epochs[0] != epochs[1]) or (
epochs[1] != epochs[2]
), "reseed_after_execution=True should produce different results per epoch"
# Test random_sample with reseed_after_execution=False
ds = base_dataset.random_sample(fraction=0.5, seed=seed_false)
epochs = collect_batches_from_epochs(ds, num_epochs=2, batch_size=5)
assert sorted(epochs[0]) == sorted(
epochs[1]
), "reseed_after_execution=False should produce same sampled items"
# Test randomize_block_order with reseed_after_execution=False
ds = base_dataset.randomize_block_order(seed=seed_false)
epochs = collect_batches_from_epochs(ds, num_epochs=2, batch_size=5)
assert (
epochs[0] == epochs[1]
), "reseed_after_execution=False should produce same block order"
@pytest.mark.parametrize(
"seed_param", [None, 42, "RandomSeedConfig_false", "RandomSeedConfig_true"]
)
def test_random_api_multiple_epochs(base_dataset, method, seed_param):
"""Comprehensive test for all methods and seed configurations across multiple
epochs."""
seed = create_seed_config(seed_param)
ds = apply_random_operation(
base_dataset, method, seed, fraction=0.5 if method == "random_sample" else None
)
epochs = collect_batches_from_epochs(ds, num_epochs=3, batch_size=5)
assert len(epochs) == 3
for i, epoch in enumerate(epochs):
if method == "random_sample":
assert len(epoch) > 0, f"Epoch {i} should have data"
else:
assert (
len(epoch) == DATASET_SIZE
), f"Epoch {i} should have all {DATASET_SIZE} items"
if seed_param is None:
all_same = all(epoch == epochs[0] for epoch in epochs)
assert (
not all_same
), f"seed=None should produce different results across epochs for {method}"
elif seed_param == 42 or seed_param == "RandomSeedConfig_false":
assert (
epochs[0] == epochs[1] == epochs[2]
), f"Fixed seed should produce same results across epochs for {method}"
elif seed_param == "RandomSeedConfig_true":
# Require at least two consecutive epochs to differ (reseed produces new orderings).
assert (epochs[0] != epochs[1]) or (
epochs[1] != epochs[2]
), f"reseed_after_execution=True should produce different results per epoch for {method}"
if __name__ == "__main__":
import sys
sys.exit(pytest.main(["-v", __file__]))