main.py 2.19 KB
Newer Older
1
2
3
#!/usr/bin/env python3

import sys
one's avatar
one committed
4
5
6
from typing import Annotated

import typer
7

one's avatar
one committed
8
from . import __version__
one's avatar
one committed
9
10
from .runner import run_with_input
from .utils import get_mpi_rank
11

one's avatar
one committed
12
13
14
app = typer.Typer(
    help=(
        "RCCL Log Parser Wrapper\n\n"
one's avatar
one committed
15
16
17
        "Usage modes:\n"
        "  1. Pipe input:    cat log.txt | xcl-lens\n"
        "  2. Read files:    xcl-lens log1.txt log2.txt\n"
one's avatar
one committed
18
19
20
21
        "  3. Wrap command:  xcl-lens ./all_reduce_perf"
    ),
    add_completion=False,
)
22

one's avatar
one committed
23

one's avatar
one committed
24
25
26
27
28
29
def _version_callback(value: bool):
    if value:
        typer.echo(f"xcl-lens {__version__}")
        raise typer.Exit()


one's avatar
one committed
30
31
32
33
34
35
36
37
38
@app.command(
    context_settings={
        "allow_extra_args": True,
        "ignore_unknown_options": True,
        "help_option_names": ["-h", "--help"],
    }
)
def main(
    ctx: typer.Context,
one's avatar
one committed
39
40
41
42
43
44
45
46
47
48
49
50
51
52
    version: Annotated[
        bool,
        typer.Option(
            "--version",
            help="Show version and exit",
            is_flag=True,
            is_eager=True,
            callback=_version_callback,
        ),
    ] = False,
    summary: Annotated[
        bool,
        typer.Option("-s", "--summary", help="Print summary report only"),
    ] = False,
one's avatar
one committed
53
54
55
56
57
58
59
    verbose: Annotated[bool, typer.Option("-v", "--verbose", help="Print verbose reports")] = False,
    hosts: Annotated[str | None, typer.Option(help="Filter by hosts (comma-separated)")] = None,
    ranks: Annotated[str | None, typer.Option(help="Filter by ranks (comma-separated)")] = None,
):
    """RCCL Log Parser Wrapper."""
    rank = get_mpi_rank()
    command: list[str] = ctx.args
60
61

    try:
one's avatar
one committed
62
63
64
65
66
67
68
69
70
71
        hosts_list = [h.strip() for h in hosts.split(",")] if hosts else None
        ranks_list = [r.strip() for r in ranks.split(",")] if ranks else None
        exit_code = run_with_input(
            command=command,
            summary=summary,
            verbose=verbose,
            hosts=hosts_list,
            ranks=ranks_list,
            rank=rank,
        )
one's avatar
one committed
72
73
        if exit_code is not None:
            sys.exit(exit_code)
74
75
    except KeyboardInterrupt:
        sys.exit(130)
one's avatar
one committed
76
77
78

    # If we got here, no command was provided and stdin is a tty
    if rank == 0:
one's avatar
one committed
79
        raise typer.Exit(code=1)
one's avatar
one committed
80
    sys.exit(1)
81
82
83


if __name__ == "__main__":
one's avatar
one committed
84
    app()