zhangzili
Initial BigMac PP Simulator Space
89cb5bf
Raw
History Blame Contribute Delete
2.23 kB
from __future__ import annotations
import math
import random
from dataclasses import dataclass
from typing import Any, Mapping
@dataclass(frozen=True)
class OpDurationSpec:
"""Normal-distribution duration config for one operation type."""
mean: float
variance: float = 0.0
min_value: float = 0.0
def sample(self, rng: random.Random) -> float:
if self.variance < 0:
raise ValueError(f"variance must be non-negative, got {self.variance}")
if self.mean < 0:
raise ValueError(f"mean must be non-negative, got {self.mean}")
if self.variance == 0:
return max(self.min_value, float(self.mean))
value = rng.gauss(float(self.mean), math.sqrt(float(self.variance)))
return max(float(self.min_value), value)
def op_type_value(op_type: Any) -> str:
"""Return a stable string value for pp_scheduler.OpType or a plain string."""
value = getattr(op_type, "value", op_type)
return str(value)
class DurationSampler:
def __init__(
self,
specs: Mapping[Any, OpDurationSpec | Mapping[str, float]],
*,
default_spec: OpDurationSpec | None = None,
seed: int | None = None,
):
self.rng = random.Random(seed)
self.default_spec = default_spec
self.specs = {
op_type_value(op_type): self._coerce_spec(spec)
for op_type, spec in specs.items()
}
def sample(self, op_type: Any, fallback_duration: float | None = None) -> float:
op_value = op_type_value(op_type)
spec = self.specs.get(op_value, self.default_spec)
if spec is not None:
return spec.sample(self.rng)
if fallback_duration is not None:
return max(0.0, float(fallback_duration))
raise KeyError(f"No duration spec for op type {op_value!r}")
@staticmethod
def _coerce_spec(spec: OpDurationSpec | Mapping[str, float]) -> OpDurationSpec:
if isinstance(spec, OpDurationSpec):
return spec
return OpDurationSpec(
mean=float(spec["mean"]),
variance=float(spec.get("variance", 0.0)),
min_value=float(spec.get("min_value", 0.0)),
)