Skip to content

fix test#72

Merged
aditchawdhary merged 3 commits into
mainfrom
fix-test
Jul 24, 2026
Merged

fix test#72
aditchawdhary merged 3 commits into
mainfrom
fix-test

Conversation

@aditchawdhary

Copy link
Copy Markdown
Collaborator

No description provided.

@github-actions

Copy link
Copy Markdown

🤖 Claude Code Review

Review

🐛 Bugs

Removed imports may break runtime behaviour if the symbols are still used

The diff removes several names from import statements without showing the corresponding removal of their usage at the call sites:

File Removed symbol Risk
nsys.py device_count_from_events, filter_device, per_device_kernel_counts If any of these are called inside nsys.py (outside this diff hunk), the module will raise NameError at runtime
torch_trace.py KernelEvent Same risk – used as a type annotation or isinstance check elsewhere in the file
optimizer/metrics.py MemcpyEvent, SyncEvent Both are concrete schema types; if metrics.py still branches on them the code silently falls through or errors
analyze.py, node_rollup.py KernelEvent Likely used in type hints; will fail under from __future__ import annotations only at runtime evaluation (e.g. get_type_hints())

Without seeing the full file bodies it is impossible to confirm these are safe, and the diff gives no evidence the usages were removed. Verify with grep -n 'KernelEvent\|MemcpyEvent\|SyncEvent\|filter_device\|device_count_from_events\|per_device_kernel_counts' across each changed file before merging.


💡 Suggestions

  • Confirm KernelEvent removal is intentional in metrics.pyFlopsModel = Callable[[KernelEvent], float] is defined two lines later in the same file. KernelEvent is still imported here (kept), but MemcpyEvent/SyncEvent removal should be audited against any isinstance(event, MemcpyEvent) dispatch patterns common in roofline/overlap metric code.

  • import sys reorder — the move from after import os to before it (alphabetical) is correct PEP 8 style; no functional concern, but worth noting it's a no-op change that adds noise to the diff.

  • Consider using TYPE_CHECKING guard for schema types only used in annotations. This would make it explicit that a symbol is annotation-only and safe to remove from the runtime import, e.g.:

    from __future__ import annotations
    from typing import TYPE_CHECKING
    if TYPE_CHECKING:
        from gitm.tracer.schema import KernelEvent

    This pattern would have made the intent of these removals self-documenting.

@github-actions

Copy link
Copy Markdown

Code Review by Gemini

The changes primarily involve removing unused imports across several files. This is a good practice for code hygiene and reducing unnecessary dependencies. No functional bugs or issues are introduced by these changes.

--- a/gitm/importers/_common.py
+++ b/gitm/importers/_common.py
@@ -1,20 +1,20 @@
 """Shared helpers for profiler importers."""
 
 from __future__ import annotations
 
 import os
+import sys
 import tempfile
 import warnings
 from collections.abc import Iterable
 from dataclasses import dataclass, field
-import sys
 from pathlib import Path
 from typing import Any
 
 from gitm.tracer.schema import KernelEvent, MemcpyEvent, SyncEvent, Trace, TraceEvent
 
 # Above this event count, skip O(n) exact-row dedupe (dominant cost on 5M-event
 # imports; identical-row rate on real profiler dumps is near zero).
 _DEDUPE_MAX_EVENTS = 100_000
 

Improvement:
The reordering of import sys is a minor stylistic change. While not strictly necessary, it aligns with PEP 8 guidelines for grouping standard library imports.

--- a/gitm/importers/analyze.py
+++ b/gitm/importers/analyze.py
@@ -11,21 +11,21 @@ from typing import Any
 
 from gitm.importers._common import ImportError, ImportStats, atomic_write_text
 from gitm.importers.detect import DetectedFormat, detect_format
 from gitm.importers.node_rollup import NodeRollup, build_node_rollup
 from gitm.optimizer.headroom import HeadroomReport, build_headroom, render_headroom_md
 from gitm.optimizer.metrics import HardwarePeak, compute_metrics
 from gitm.optimizer.preconditions import GateContext
 from gitm.optimizer.qualification import QualificationResult, qualify
 from gitm.planner.context import peak_for_sku
 from gitm.tracer.capture import write_trace_jsonl
-from gitm.tracer.schema import KernelEvent, Trace
+from gitm.tracer.schema import Trace
 
 # Default catalogue peak when SKU is unknown (A100 PCIe figures; called out in caveats).
 _DEFAULT_PEAK = HardwarePeak(name="A100", peak_flops=312e12, peak_bw_bytes_s=1555e9)
 
 
 @dataclass
 class DeviceAnalysis:
     """One device's metrics + headroom within a multi-device workload file."""
 
     device_id: int

Improvement:
Removing KernelEvent from the import list is correct as it is not used in this file.

--- a/gitm/importers/node_rollup.py
+++ b/gitm/importers/node_rollup.py
@@ -4,21 +4,21 @@ Computes device skew, collective communication share, and exposed (non-overlappe
 communication time. Pure timestamp math — no invented counters.
 """
 
 from __future__ import annotations
 
 import re
 from dataclasses import dataclass, field
 from typing import Any
 
 from gitm.optimizer.metrics import _merge_intervals
-from gitm.tracer.schema import KernelEvent, Trace
+from gitm.tracer.schema import Trace
 
 # Collective kernel name patterns (case-insensitive). One module-level table;
 # each entry is a substring match against the demangled/exported kernel name.
 # Comment: covers NCCL device kernels and common collective op labels in chrome
 # traces. Unknown collective libraries (e.g. proprietary) will not match —
 # zero hits on multi-device is reported as inconclusive, not zero communication.
 _COMM_PATTERNS: tuple[tuple[str, str], ...] = (
     ("nccl", "NCCL library prefix (any nccl* kernel)"),
     ("ncclkernel", "NCCL device kernel entry points"),
     ("allreduce", "AllReduce collective"),

Improvement:
Removing KernelEvent from the import list is correct as it is not used in this file.

--- a/gitm/importers/nsys.py
+++ b/gitm/importers/nsys.py
@@ -10,25 +10,22 @@ import sqlite3
 import subprocess
 import tempfile
 from collections.abc import Iterator
 from pathlib import Path
 from typing import Any
 
 from gitm.importers._common import (
     ImportError,
     ImportStats,
     as_int,
-    device_count_from_events,
     file_mtime_ns,
-    filter_device,
     finish_trace,
-    per_device_kernel_counts,
 )
 from gitm.tracer.schema import KernelEvent, MemcpyEvent, SyncEvent, Trace, TraceEvent
 
 # ---------------------------------------------------------------------------
 # CUPTI enum maps — integers differ across CUPTI versions; one table per kind.
 # Values annotated with the CUPTI header name from cupti_activity.h.
 # ---------------------------------------------------------------------------
 
 # CUpti_ActivityMemoryKind
 _MEMORY_KIND: dict[int, str] = {

Improvement:
Removing device_count_from_events, filter_device, and per_device_kernel_counts from the import list is correct as they are not used in this file.

--- a/gitm/importers/torch_trace.py
+++ b/gitm/importers/torch_trace.py
@@ -17,21 +17,21 @@ from typing import Any
 from gitm.importers._common import (
     ImportError,
     ImportStats,
     as_int,
     device_count_from_events,
     file_mtime_ns,
     filter_device,
     finish_trace,
     per_device_kernel_counts,
 )
-from gitm.tracer.schema import KernelEvent, MemcpyEvent, Trace, TraceEvent
+from gitm.tracer.schema import MemcpyEvent, Trace, TraceEvent
 
 # Max decompressed size for .json.gz (customer dumps can be multi-GB).
 DEFAULT_MAX_DECOMPRESSED_BYTES = 20 * 1024 ** 3  # 20 GiB
 
 # Complete events only.
 _PHASE_COMPLETE = "X"
 
 # Kernel categories across torch versions.
 _KERNEL_CATS = frozenset({"kernel", "Kernel", "gpu_op", "gpu_memcpy", "Memcpy"})
 _MEMCPY_CATS = frozenset({"gpu_memcpy", "Memcpy", "memcpy", "gpu_memset"})  # memset skipped later

Improvement:
Removing KernelEvent from the import list is correct as it is not used in this file.

--- a/gitm/optimizer/metrics.py
+++ b/gitm/optimizer/metrics.py
@@ -19,21 +19,21 @@ MBU (Memory Bandwidth Utilization) — achieved bytes/s ÷ peak bandwidth,
 HFU vs MFU is deliberately explicit: HFU counts every FLOP the silicon issued,
 MFU only the FLOPs that advanced the model. Reporting both makes "the GPU is
 busy" (high HFU) vs "the GPU is doing useful work" (high MFU) separable.
 """
 
 from __future__ import annotations
 
 from collections.abc import Callable, Iterable
 from dataclasses import dataclass
 
-from gitm.tracer.schema import KernelEvent, MemcpyEvent, SyncEvent, Trace
+from gitm.tracer.schema import KernelEvent, Trace
 
 FlopsModel = Callable[[KernelEvent], float]
 
 
 @dataclass(frozen=True)
 class HardwarePeak:
     """Vendor peak rates for the SKU under test (dense, not sparse)."""
 
     name: str
     peak_flops: float  # FLOP/s

Improvement:
Removing MemcpyEvent and SyncEvent from the import list is correct as they are not used in this file. KernelEvent is correctly retained as it is used in FlopsModel.

@github-actions

Copy link
Copy Markdown

🤖 Claude Code Review

Code Review

🐛 Bugs

isinstance() with union types is broken on older Python

# torch_trace.py line ~94
if isinstance(val, (list | tuple)) and len(val) >= 1:

# tests/test_importers_hypothesis.py
assert isinstance(ev, (KernelEvent | LightKernel))
assert isinstance(ev, (KernelEvent | MemcpyEvent | LightKernel | LightMemcpy))

isinstance(x, (A | B)) syntax requires Python 3.10+. The X | Y union inside a tuple literal creates a types.UnionType object, not a tuple of types — this will raise TypeError: Subscripted generics cannot be used with class and instance checks on Python 3.9 and earlier. The original isinstance(val, (list, tuple)) form is correct and universally supported.

This is a straight regression — the original code was correct, the new code is broken on any Python < 3.10. Fix by reverting to the tuple-of-types form:

# Correct
isinstance(val, (list, tuple))
isinstance(ev, (KernelEvent, LightKernel))

If Python 3.10+ is a hard requirement, that constraint should be explicit in pyproject.toml/setup.cfg and CI matrix.


💡 Suggestions

Removed imports from nsys.py — verify call sites are gone

device_count_from_events, filter_device, and per_device_kernel_counts are dropped from nsys.py's imports. If any code path inside nsys.py still calls these (e.g. conditionally, or in a branch not visible in this diff), it will fail at runtime rather than import time. Worth a quick grep to confirm all call sites were removed alongside the imports.

KernelEvent removed from analyze.py and node_rollup.py

Same concern — confirm KernelEvent is not referenced anywhere in those modules' bodies (type annotations, isinstance checks, docstrings that are eval'd, etc.). A pyflakes/ruff pass would catch any stragglers automatically.

MemcpyEvent/SyncEvent dropped from metrics.py

If metrics.py operates on Trace objects that contain MemcpyEvent/SyncEvent members, removing those imports means any runtime path that constructs or inspects them will fail. Confirm the module genuinely has no remaining references.

@github-actions

Copy link
Copy Markdown

Code Review by Gemini

Here's a review of the provided code changes:

Potential Issues

1. Python Version Compatibility for isinstance Syntax
The changes introduce the type1 | type2 syntax within isinstance() calls. This syntax for type unions in isinstance() is only valid in Python 3.10 and later. If the project's minimum supported Python version is 3.9 or earlier, these changes will cause a TypeError at runtime.

  • File: gitm/importers/torch_trace.py

    --- a/gitm/importers/torch_trace.py
    +++ b/gitm/importers/torch_trace.py
    @@ -84,7 +84,7 @@ def _arg_get(args: dict[str, Any] | None, keys: tuple[str, ...]) -> Any:
     def _as_dims(val: Any) -> tuple[int, int, int]:
         if val is None:
             return (1, 1, 1)
    -    if isinstance(val, (list, tuple)) and len(val) >= 1:
    +    if isinstance(val, (list | tuple)) and len(val) >= 1:
             x = as_int(val[0], 1) if len(val) > 0 else 1
             y = as_int(val[1], 1) if len(val) > 1 else 1
             z = as_int(val[2], 1) if len(val) > 2 else 1

    Suggestion: If Python 3.9 or earlier needs to be supported, change line 87 back to:

    if isinstance(val, (list, tuple)) and len(val) >= 1:
  • File: tests/test_importers_hypothesis.py

    --- a/tests/test_importers_hypothesis.py
    +++ b/tests/test_importers_hypothesis.py
    @@ -34,7 +34,7 @@ def test_prop_us_to_ns_monotonic(ts: float, dur: float):
                 }
             )
             # Default import path uses LightKernel for scale; --strict uses KernelEvent.
    -        assert isinstance(ev, (KernelEvent, LightKernel))
    +        assert isinstance(ev, (KernelEvent | LightKernel))
             assert ev.start_ns == int(ts * 1000.0)
             assert ev.end_ns == int((ts + dur) * 1000.0)
             assert ev.end_ns >= ev.start_ns or dur == 0.0
    @@ -67,7 +67,7 @@ def test_prop_missing_args_never_crash(cat, name, has_grid, has_stream, has_devi
         assume("memset" not in name.lower())
         ev = event_from_chrome(
             {"ph": "X", "cat": cat, "name": name, "ts": 1.0, "dur": 2.0, "args": args}
         )
         # May be None for weird name/cat combos; must not raise.
         if ev is not None:
    -        assert isinstance(ev, (KernelEvent, MemcpyEvent, LightKernel, LightMemcpy))
    +        assert isinstance(ev, (KernelEvent | MemcpyEvent | LightKernel | LightMemcpy))
             assert getattr(ev, "kind", None) in ("kernel", "memcpy")
             assert ev.end_ns >= ev.start_ns
             # Light events are not pydantic; only validate the full Trace path

    Suggestion: If Python 3.9 or earlier needs to be supported, change line 37 back to:

    assert isinstance(ev, (KernelEvent, LightKernel))

    And change line 70 back to:

    assert isinstance(ev, (KernelEvent, MemcpyEvent, LightKernel, LightMemcpy))

2. Verification of Removed Imports
Several imports have been removed across different files. While removing unused imports is good practice, please verify that the removed entities are indeed no longer used in their respective files to avoid runtime errors.

  • File: gitm/importers/analyze.py

    • Removed KernelEvent from gitm.tracer.schema.
    • Action: Please verify that KernelEvent is not used anywhere in analyze.py.
  • File: gitm/importers/node_rollup.py

    • Removed KernelEvent from gitm.tracer.schema.
    • Action: Please verify that KernelEvent is not used anywhere in node_rollup.py.
  • File: gitm/importers/nsys.py

    • Removed device_count_from_events, filter_device, per_device_kernel_counts from gitm.importers._common.
    • Action: Please verify that these functions are not used anywhere in nsys.py.
  • File: gitm/importers/torch_trace.py

    • Removed KernelEvent from gitm.tracer.schema.
    • Action: Please verify that KernelEvent is not used anywhere in torch_trace.py.
  • File: gitm/optimizer/metrics.py

    • Removed MemcpyEvent, SyncEvent from gitm.tracer.schema.
    • Action: Please verify that MemcpyEvent and SyncEvent are not used anywhere in metrics.py.

@github-actions

Copy link
Copy Markdown

🤖 Claude Code Review

Code Review

🐛 Bugs

isinstance with union type syntax is broken on Python < 3.10

# torch_trace.py line ~94
if isinstance(val, (list | tuple)) and len(val) >= 1:

# tests/test_importers_hypothesis.py
assert isinstance(ev, (KernelEvent | LightKernel))
assert isinstance(ev, (KernelEvent | MemcpyEvent | LightKernel | LightMemcpy))

isinstance() does not accept X | Y union syntax inside a tuple wrapper — that's doubly wrong. The | union operator for isinstance is valid only as a bare second argument (isinstance(x, A | B)) on Python 3.10+. Wrapping it in a tuple (A | B) evaluates to a 1-tuple containing a types.UnionType object, which isinstance will reject with TypeError: Subscripted generics cannot be used with class and instance checks on 3.10, or simply fail on 3.9.

Correct forms:

# Python 3.10+ only:
isinstance(val, list | tuple)

# Compatible with 3.8+:
isinstance(val, (list, tuple))

The test file also has from __future__ import annotations which does not help here — that only affects annotation evaluation, not runtime isinstance calls.


💡 Suggestions

Removed imports from _common.py in nsys.py — verify dead code

device_count_from_events, filter_device, and per_device_kernel_counts were removed from the nsys.py import. Confirm these functions are genuinely unused in that module now; if nsys.py handles multi-GPU traces, silently dropping filter_device could mean device-filtering logic was also removed without a clear replacement.

KernelEvent removed from analyze.py and node_rollup.py

Both modules dropped KernelEvent from their schema imports. If any type annotations or runtime checks in those files referenced KernelEvent directly (even in docstrings or cast() calls not shown in the diff), this will produce NameError at runtime. Worth a grep -n KernelEvent pass over those files.

_as_dims redundant length check

if isinstance(val, (list | tuple)) and len(val) >= 1:  # outer guard
    x = as_int(val[0], 1) if len(val) > 0 else 1       # redundant re-check

The inner len(val) > 0 check is unreachable given the outer >= 1 guard. Pre-existed but worth cleaning up since this function was touched.

@github-actions

Copy link
Copy Markdown

Code Review by Gemini

## Code Review

### gitm/importers/_common.py

**Suggestion:**
The reordering of `import sys` is a minor stylistic change and doesn't introduce any functional issues. It's generally good practice to group standard library imports together.

### gitm/importers/analyze.py
### gitm/importers/node_rollup.py
### gitm/importers/nsys.py
### gitm/importers/torch_trace.py
### gitm/optimizer/metrics.py

**Potential Issue:**
Several imports (`KernelEvent`, `MemcpyEvent`, `SyncEvent`, `device_count_from_events`, `filter_device`, `per_device_kernel_counts`) have been removed from various files. While this is often a cleanup of unused imports, please ensure that these types/functions are indeed no longer used within the respective files. If they are still referenced, this change will lead to runtime errors.

### gitm/importers/torch_trace.py

**Bug:**
The change in `isinstance` syntax from `(list, tuple)` to `(list | tuple)` is only valid in Python 3.10 and later. According to `pyproject.toml`, the project supports Python `>=3.9`. In Python 3.9, `type | type` is not supported for `isinstance` and will raise a `TypeError`.

**Proposed change:**
```diff
--- a/gitm/importers/torch_trace.py
+++ b/gitm/importers/torch_trace.py
@@ -84,7 +84,7 @@ def _arg_get(args: dict[str, Any] | None, keys: tuple[str, ...]) -> Any:
 def _as_dims(val: Any) -> tuple[int, int, int]:
     if val is None:
         return (1, 1, 1)
-    if isinstance(val, (list | tuple)) and len(val) >= 1:
+    if isinstance(val, (list, tuple)) and len(val) >= 1:
         x = as_int(val[0], 1) if len(val) > 0 else 1
         y = as_int(val[1], 1) if len(val) > 1 else 1
         z = as_int(val[2], 1) if len(val) > 2 else 1

pyproject.toml

Suggestion:
Adding hypothesis>=6.0 to the dev dependencies is a good addition for property-based testing, aligning with the new test file.

tests/test_importers_hypothesis.py

Bug:
Similar to gitm/importers/torch_trace.py, the isinstance syntax using | for type unions is not compatible with Python versions prior to 3.10. Since pyproject.toml specifies python = ">=3.9", these changes will cause TypeError in Python 3.9 environments.

Proposed change:

--- a/tests/test_importers_hypothesis.py
+++ b/tests/test_importers_hypothesis.py
@@ -34,7 +34,7 @@ def test_prop_us_to_ns_monotonic(ts: float, dur: float):
         }
     )
     # Default import path uses LightKernel for scale; --strict uses KernelEvent.
-    assert isinstance(ev, (KernelEvent, LightKernel))
+    assert isinstance(ev, (KernelEvent, LightKernel))
     assert ev.start_ns == int(ts * 1000.0)
     assert ev.end_ns == int((ts + dur) * 1000.0)
     assert ev.end_ns >= ev.start_ns or dur == 0.0
@@ -67,7 +67,7 @@ def test_prop_missing_args_never_crash(cat, name, has_grid, has_stream, has_devi
     # memset names must skip for Memcpy-ish cats
     assume("memset" not in name.lower())
     ev = event_from_chrome(
         {"ph": "X", "cat": cat, "name": name, "ts": 1.0, "dur": 2.0, "args": args}
     )
     # May be None for weird name/cat combos; must not raise.
     if ev is not None:
-        assert isinstance(ev, (KernelEvent | MemcpyEvent | LightKernel | LightMemcpy))
+        assert isinstance(ev, (KernelEvent, MemcpyEvent, LightKernel, LightMemcpy))
         assert getattr(ev, "kind", None) in ("kernel", "memcpy")
         assert ev.end_ns >= ev.start_ns
         # Light events are not pydantic; only validate the full Trace path

@aditchawdhary
aditchawdhary merged commit b785456 into main Jul 24, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant