Align Frontier piecewise graph profiles
This commit is contained in:
@@ -9,7 +9,7 @@ import math
|
||||
import statistics
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
from typing import Any, Callable
|
||||
|
||||
import torch
|
||||
import vllm
|
||||
@@ -40,6 +40,12 @@ def parse_args() -> argparse.Namespace:
|
||||
parser.add_argument("--repeats", type=int, default=5)
|
||||
parser.add_argument("--device", default="cuda:0")
|
||||
parser.add_argument("--check-reference", action="store_true")
|
||||
parser.add_argument(
|
||||
"--profile-method",
|
||||
choices=("cuda_event", "record_function"),
|
||||
default="cuda_event",
|
||||
)
|
||||
parser.add_argument("--frontier-source", type=Path)
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
@@ -59,6 +65,34 @@ def stats_ms(samples: list[float]) -> dict[str, float]:
|
||||
}
|
||||
|
||||
|
||||
def measure_kernel_only_ms(
|
||||
fn: Callable[[], torch.Tensor],
|
||||
*,
|
||||
warmup_iters: int,
|
||||
repeats: int,
|
||||
trace_root: Path,
|
||||
operation_name: str,
|
||||
record_function_tracer: type,
|
||||
) -> tuple[torch.Tensor, dict[str, float]]:
|
||||
"""Use Frontier's KERNEL_ONLY contract, not a CUDA-event relabel."""
|
||||
result = None
|
||||
for _ in range(warmup_iters):
|
||||
result = fn()
|
||||
torch.accelerator.synchronize()
|
||||
|
||||
tracer = record_function_tracer(str(trace_root))
|
||||
with tracer:
|
||||
for _ in range(repeats):
|
||||
with torch.profiler.record_function(f"vidur_{operation_name}"):
|
||||
result = fn()
|
||||
stats = tracer.get_operation_time_stats()
|
||||
if operation_name not in stats:
|
||||
raise RuntimeError(f"missing RecordFunctionTracer stats for {operation_name}")
|
||||
if result is None:
|
||||
raise RuntimeError("kernel-only profiler executed no MoE step")
|
||||
return result, {name: float(value) for name, value in stats[operation_name].items()}
|
||||
|
||||
|
||||
def routing_inputs(
|
||||
mode: str, num_tokens: int, device: torch.device
|
||||
) -> tuple[torch.Tensor, torch.Tensor, dict[str, Any]]:
|
||||
@@ -145,6 +179,8 @@ def main() -> None:
|
||||
raise SystemExit(
|
||||
f"model contract mismatch: expected {expected_model}, got {observed_model}"
|
||||
)
|
||||
if args.profile_method == "record_function" and args.frontier_source is None:
|
||||
raise SystemExit("--frontier-source is required for --profile-method record_function")
|
||||
|
||||
from vllm.config import ParallelConfig, VllmConfig, set_current_vllm_config
|
||||
from vllm.model_executor.layers.fused_moe.activation import MoEActivation
|
||||
@@ -163,10 +199,22 @@ def main() -> None:
|
||||
from vllm.utils.math_utils import next_power_of_2
|
||||
from vllm.v1.worker.workspace import init_workspace_manager
|
||||
|
||||
record_function_tracer = None
|
||||
if args.profile_method == "record_function":
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, str(args.frontier_source.resolve()))
|
||||
from frontier.profiling.utils.record_function_tracer import RecordFunctionTracer
|
||||
|
||||
record_function_tracer = RecordFunctionTracer
|
||||
|
||||
device = torch.device(args.device)
|
||||
torch.accelerator.set_device_index(device)
|
||||
torch.manual_seed(20260716)
|
||||
init_workspace_manager(args.device)
|
||||
args.output.parent.mkdir(parents=True, exist_ok=True)
|
||||
if args.profile_method == "record_function":
|
||||
(args.output.parent / "profiler_traces").mkdir(exist_ok=True)
|
||||
max_num_tokens = next_power_of_2(max(args.num_tokens))
|
||||
|
||||
rows: list[dict[str, Any]] = []
|
||||
@@ -257,8 +305,8 @@ def main() -> None:
|
||||
routing_mode, num_tokens, device
|
||||
)
|
||||
|
||||
for _ in range(args.warmup_iters):
|
||||
output = kernel.apply(
|
||||
def run_kernel() -> torch.Tensor:
|
||||
return kernel.apply(
|
||||
hidden_states=hidden,
|
||||
w1=w13_kernel,
|
||||
w2=w2_kernel,
|
||||
@@ -269,27 +317,30 @@ def main() -> None:
|
||||
expert_map=None,
|
||||
apply_router_weight_on_input=False,
|
||||
)
|
||||
torch.accelerator.synchronize()
|
||||
|
||||
samples: list[float] = []
|
||||
for _ in range(args.repeats):
|
||||
start = torch.cuda.Event(enable_timing=True)
|
||||
end = torch.cuda.Event(enable_timing=True)
|
||||
start.record()
|
||||
output = kernel.apply(
|
||||
hidden_states=hidden,
|
||||
w1=w13_kernel,
|
||||
w2=w2_kernel,
|
||||
topk_weights=topk_weights,
|
||||
topk_ids=topk_ids,
|
||||
activation=MoEActivation.SILU,
|
||||
global_num_experts=NUM_EXPERTS,
|
||||
expert_map=None,
|
||||
apply_router_weight_on_input=False,
|
||||
if args.profile_method == "record_function":
|
||||
output, time_ms = measure_kernel_only_ms(
|
||||
run_kernel,
|
||||
warmup_iters=args.warmup_iters,
|
||||
repeats=args.repeats,
|
||||
trace_root=args.output.parent,
|
||||
operation_name="moe_grouped_gemm",
|
||||
record_function_tracer=record_function_tracer,
|
||||
)
|
||||
end.record()
|
||||
else:
|
||||
for _ in range(args.warmup_iters):
|
||||
output = run_kernel()
|
||||
torch.accelerator.synchronize()
|
||||
samples.append(float(start.elapsed_time(end)))
|
||||
samples: list[float] = []
|
||||
for _ in range(args.repeats):
|
||||
start = torch.cuda.Event(enable_timing=True)
|
||||
end = torch.cuda.Event(enable_timing=True)
|
||||
start.record()
|
||||
output = run_kernel()
|
||||
end.record()
|
||||
torch.accelerator.synchronize()
|
||||
samples.append(float(start.elapsed_time(end)))
|
||||
time_ms = stats_ms(samples)
|
||||
|
||||
if output.shape != hidden.shape or not torch.isfinite(output).all():
|
||||
raise SystemExit(
|
||||
@@ -316,7 +367,7 @@ def main() -> None:
|
||||
"backend": backend.value,
|
||||
"intermediate_size_per_partition": INTERMEDIATE_DIM // tp,
|
||||
"output_is_reduced": kernel.output_is_reduced(),
|
||||
"time_ms": stats_ms(samples),
|
||||
"time_ms": time_ms,
|
||||
"routing_load": load,
|
||||
}
|
||||
rows.append(row)
|
||||
@@ -350,6 +401,7 @@ def main() -> None:
|
||||
"weight_quantization": "none",
|
||||
"top_k": TOP_K,
|
||||
"norm_topk_prob": True,
|
||||
"profile_method": args.profile_method,
|
||||
},
|
||||
"measurement_scope": (
|
||||
"one TP-local weight shard: vLLM modular MoE prepare+FlashInfer "
|
||||
@@ -357,7 +409,6 @@ def main() -> None:
|
||||
),
|
||||
"rows": rows,
|
||||
}
|
||||
args.output.parent.mkdir(parents=True, exist_ok=True)
|
||||
args.output.write_text(json.dumps(payload, indent=2, sort_keys=True) + "\n")
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user