Model critical EP lane for Frontier prefill
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
diff --git a/frontier/execution_time_predictor/sklearn_moe_execution_time_predictor.py b/frontier/execution_time_predictor/sklearn_moe_execution_time_predictor.py
|
||||
--- a/frontier/execution_time_predictor/sklearn_moe_execution_time_predictor.py
|
||||
+++ b/frontier/execution_time_predictor/sklearn_moe_execution_time_predictor.py
|
||||
@@ -386,0 +387,58 @@
|
||||
+ def _get_critical_prefill_ep_lane_tokens(
|
||||
+ self,
|
||||
+ total_routed_tokens: int,
|
||||
+ layer_id: int,
|
||||
+ ) -> Dict[int, int]:
|
||||
+ """Return the routed-token allocation for the slowest prefill EP lane.
|
||||
+
|
||||
+ A monolithic prefill starts with a global ``tokens * topk`` routing
|
||||
+ population, but each EP rank executes only the assignments for its local
|
||||
+ experts. The ranks synchronize after the MoE block, so the layer cost is
|
||||
+ governed by the slowest lane rather than by either the global population
|
||||
+ or the average lane.
|
||||
+ """
|
||||
+ total_experts = int(self._replica_config.total_expert_num)
|
||||
+ lane_count = int(self._moe_ep_size)
|
||||
+ if total_experts <= 0 or lane_count <= 1 or total_experts % lane_count != 0:
|
||||
+ raise ValueError(
|
||||
+ "Prefill EP routing requires total_expert_num to be positive and "
|
||||
+ f"divisible by moe_ep_size > 1; got total_expert_num={total_experts}, "
|
||||
+ f"moe_ep_size={lane_count}"
|
||||
+ )
|
||||
+
|
||||
+ experts_per_lane = total_experts // lane_count
|
||||
+ global_tokens = self._get_global_per_expert_tokens(
|
||||
+ total_routed_tokens=total_routed_tokens,
|
||||
+ layer_id=layer_id,
|
||||
+ )
|
||||
+ lane_tokens: List[Dict[int, int]] = [
|
||||
+ {local_expert_id: 0 for local_expert_id in range(experts_per_lane)}
|
||||
+ for _ in range(lane_count)
|
||||
+ ]
|
||||
+ for global_expert_id, token_count in global_tokens.items():
|
||||
+ lane_id = int(global_expert_id) // experts_per_lane
|
||||
+ local_expert_id = int(global_expert_id) % experts_per_lane
|
||||
+ lane_tokens[lane_id][local_expert_id] = int(token_count)
|
||||
+
|
||||
+ def _lane_compute_score(allocation: Dict[int, int]) -> float:
|
||||
+ features = self._build_moe_load_imbalance_features(allocation)
|
||||
+ score = 0.0
|
||||
+ for operation in ("moe_shuffling", "moe_grouped_gemm"):
|
||||
+ prediction = self._predictions.get(operation)
|
||||
+ if isinstance(prediction, dict) and prediction.get(
|
||||
+ "_on_demand_prediction", False
|
||||
+ ):
|
||||
+ score += float(
|
||||
+ self._get_on_demand_prediction(operation, features)
|
||||
+ )
|
||||
+ return score
|
||||
+
|
||||
+ return max(
|
||||
+ lane_tokens,
|
||||
+ key=lambda allocation: (
|
||||
+ _lane_compute_score(allocation),
|
||||
+ sum(allocation.values()),
|
||||
+ tuple(allocation.values()),
|
||||
+ ),
|
||||
+ )
|
||||
+
|
||||
@@ -1023,0 +1082,13 @@
|
||||
+
|
||||
+ from frontier.entities import EPBatchGroup
|
||||
+
|
||||
+ is_monolithic_prefill_ep = (
|
||||
+ self._moe_ep_size > 1
|
||||
+ and not isinstance(batch, EPBatchGroup)
|
||||
+ and not bool(getattr(batch, "is_pure_decode_batch", False))
|
||||
+ )
|
||||
+ if is_monolithic_prefill_ep:
|
||||
+ return self._get_critical_prefill_ep_lane_tokens(
|
||||
+ total_routed_tokens=num_tokens * self._router_topk,
|
||||
+ layer_id=layer_id,
|
||||
+ )
|
||||
Reference in New Issue
Block a user