|
48 | 48 | # One worker per GPU, kept alive while idle so we can read its measured perf. |
49 | 49 | ENDPOINT_CONFIG = {"cold_workers": 1, "max_workers": 1, "min_load": 1.0} |
50 | 50 |
|
51 | | -# Timing knobs, in the order they fire during a run. |
52 | | -RENTAL_TIMEOUT = 120 # give up if the autoscaler hasn't rented a worker by now |
53 | | -DEFAULT_BENCHMARK_TIMEOUT = 30 * 60 # default --timeout: max wait for a measured result |
54 | | -WORKER_POLL_INTERVAL = 10.0 # base seconds between worker-status polls (jitter added at call site) |
| 51 | +RENTAL_TIMEOUT = 120 |
| 52 | +DEFAULT_BENCHMARK_TIMEOUT = 30 * 60 |
| 53 | +WORKER_POLL_INTERVAL = 10.0 |
55 | 54 | PARALLEL_SUBMIT_DELAY = 4.0 # spacing between parallel endpoint submits |
56 | 55 | MAX_ABANDONS = 3 # bail after this many workers vanish without one reaching idle |
57 | 56 |
|
58 | | -# Worker states the autoscaler does NOT recover from; a run fails if every worker |
59 | | -# sits in one for >TERMINAL_GRACE_SECONDS without any reaching idle. `error` is |
60 | | -# excluded since the autoscaler retries it (error -> rebooting -> model_loading). |
61 | | -TERMINAL_STATES = {"stopped", "destroying", "unavail"} |
| 57 | +# states in which the autoscaler shouldnt retry the worker |
| 58 | +TERMINAL_STATES = {"stopped", "destroying", "unavail"} |
62 | 59 | TERMINAL_GRACE_SECONDS = 30 |
63 | | - |
64 | | -# Per-spec statuses that freeze the live-table elapsed timer (work is over). |
65 | 60 | TERMINAL_STATUSES = {"done", "skipped", "timeout", "failed", "no_worker"} |
66 | 61 |
|
67 | 62 |
|
@@ -111,17 +106,14 @@ def _per_card_vram_mb(gpu_name): |
111 | 106 |
|
112 | 107 | def parse_gpu_spec(token, default_num_gpus): |
113 | 108 | """Parse a GPU token into (canonical_gpu_name, num_gpus). |
114 | | -
|
115 | | - "2x RTX_4090" -> ("RTX 4090", 2). Accepts rtx_4090 / RTX 4090 / Rtx_4090 and |
116 | | - canonicalizes to the marketplace's exact name. An inline Nx prefix wins over |
117 | | - --num_gpus; with neither, falls back to default_num_gpus. |
| 109 | + Example: 2x RTX_4090" -> ("RTX 4090", 2). |
118 | 110 | """ |
119 | 111 |
|
120 | | - # so users can input "rtx_4090" or "RTX 4090" or "Rtx_4090" and all resolves to "RTX 4090" |
| 112 | + # so "rtx_4090", "RTX 4090", "Rtx_4090" all map to "RTX 4090" |
121 | 113 | canonical = _canonical_gpu_names() |
122 | 114 |
|
123 | 115 | token = token.strip() |
124 | | - # converts "2x RTX_4090" to ("RTX 4090", 2) |
| 116 | + # string to tuple. "2x RTX_4090" to ("RTX 4090", 2) |
125 | 117 | m = re.match(r"^(\d+)[\s_]*x[\s_]*(.+)$", token, re.IGNORECASE) |
126 | 118 | if m: |
127 | 119 | raw_name, n = m.group(2).strip().replace("_", " "), int(m.group(1)) |
@@ -635,11 +627,11 @@ def benchmark_gpu(vast, *, gpu_name, num_gpus, timeout, |
635 | 627 |
|
636 | 628 | @parser.command( |
637 | 629 | argument("--template_hash", type=str, default=None, |
638 | | - help="(required, one of --template_hash or --template_id) template hash to benchmark"), |
| 630 | + help="the template to benchmark; provide either --template_hash or --template_id"), |
639 | 631 | argument("--template_id", type=int, default=None, |
640 | | - help="(required, one of --template_hash or --template_id) template id"), |
| 632 | + help="the template to benchmark; provide either --template_hash or --template_id"), |
641 | 633 | argument("--gpus", type=str, |
642 | | - help="comma-separated GPU names (e.g. RTX_4090,RTX_3090); optional Nx prefix takes precedence over --num_gpus (e.g. \"2x RTX_4090\")"), |
| 634 | + help="comma-separated GPU names to benchmark (e.g. RTX_4090,RTX_3090). Prefix a name with a count to set GPUs per instance, e.g. \"2x RTX_4090\" (overrides --num_gpus)"), |
643 | 635 | argument("--num_gpus", type=int, default=None, |
644 | 636 | help="GPUs per instance for tokens without an Nx prefix (default 1); overridden by inline Nx in --gpus"), |
645 | 637 | argument("--timeout", type=int, default=DEFAULT_BENCHMARK_TIMEOUT, |
@@ -690,18 +682,19 @@ def run__benchmarks(args): |
690 | 682 | "(run `vastai run benchmarks --help` for usage)", |
691 | 683 | file=sys.stderr) |
692 | 684 | return 1 |
693 | | - # bump retry budget so parallel polls don't exhaust VastClient's tiny default (3 attempts, ~0.7s) under autoscaler rate limits. |
694 | | - retry = max(args.retry, 8) |
695 | | - vast = VastAI(api_key=args.api_key, server_url=args.url, retry=retry, |
696 | | - explain=getattr(args, 'explain', False), |
697 | | - curl=getattr(args, 'curl', False)) |
698 | | - |
699 | 685 | if args.template_id is not None: |
700 | 686 | query = {"id": {"eq": args.template_id}} |
701 | 687 | ident = f"id={args.template_id}" |
702 | 688 | else: |
703 | 689 | query = {"hash_id": {"eq": args.template_hash}} |
704 | 690 | ident = f"hash={args.template_hash}" |
| 691 | + |
| 692 | + # bump retry budget so parallel polls don't exhaust VastClient's tiny default (3 attempts, ~0.7s) under autoscaler rate limits. |
| 693 | + retry = max(args.retry, 8) |
| 694 | + vast = VastAI(api_key=args.api_key, server_url=args.url, retry=retry, |
| 695 | + explain=getattr(args, 'explain', False), |
| 696 | + curl=getattr(args, 'curl', False)) |
| 697 | + |
705 | 698 | templates = vast.search_templates(query=query) |
706 | 699 | if not templates: |
707 | 700 | print(f"error: template not found ({ident})", file=sys.stderr) |
|
0 commit comments