Skip to content

Commit 86dca3b

Browse files
[lang] Add pass-through flags for the ptx compiler
Signed-off-by: Asher Mancinelli <amancinelli@nvidia.com>
1 parent 17524d6 commit 86dca3b

4 files changed

Lines changed: 104 additions & 5 deletions

File tree

experimental/cuda-lang/src/cuda/lang/_compile.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,16 @@ def mlir2cubin(
6060
gpu_name: str,
6161
arch: str,
6262
emit_ptx: bool = False,
63+
ptx_compiler_options: Sequence[str] = (),
6364
) -> MLIR2CubinResult:
6465
executable = get_compiler_binary_path()
6566
argv = [executable, "-", "-o", "-", f"--gpu-name={gpu_name}", f"--arch={arch}"]
6667
custom_flags = os.environ.get("CUDA_LANG_MLIR2CUBIN_FLAGS", None)
6768

69+
argv.extend(
70+
f"--ptx-compiler-option={option}" for option in ptx_compiler_options
71+
)
72+
6873
if custom_flags is not None:
6974
argv.extend(custom_flags.split())
7075

@@ -266,10 +271,18 @@ def _dump(phase: str, contents: object) -> None:
266271
arch = arch or cc.arch + suffix
267272

268273
need_ptx = log_flags.log_ptx or keep_ptx
274+
ptx_compiler_options = compiler_options._ptx_compiler_options
269275
compiled = mlir2cubin(
270-
mlir_text, gpu_name=gpu_name, arch=arch, emit_ptx=need_ptx
276+
mlir_text,
277+
gpu_name=gpu_name,
278+
arch=arch,
279+
emit_ptx=need_ptx,
280+
ptx_compiler_options=ptx_compiler_options,
271281
)
272282

283+
if compiled.stderr and ptx_compiler_options:
284+
_dump("PTX compiler", compiled.stderr.decode())
285+
273286
if need_ptx:
274287
assert compiled.ptx is not None
275288

experimental/cuda-lang/src/cuda/lang/_compiler_options.py

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# SPDX-License-Identifier: Apache-2.0
44

55
from __future__ import annotations
6-
from dataclasses import dataclass
6+
from dataclasses import dataclass, field, fields
77
from ._exception import TypeCheckingError
88

99

@@ -14,6 +14,22 @@ class CompilerOptions:
1414
max_blocks_per_cluster: int | None = None
1515
max_registers_per_thread: int | None = None
1616
min_blocks_per_sm: int | None = None
17+
_ptx_compiler_verbose: bool = field(
18+
default=False,
19+
metadata={"PTX_FLAG": "--verbose"},
20+
)
21+
_ptx_compiler_warn_on_local_memory_usage: bool = field(
22+
default=False,
23+
metadata={"PTX_FLAG": "--warn-on-local-memory-usage"},
24+
)
25+
_ptx_compiler_warn_on_spills: bool = field(
26+
default=False,
27+
metadata={"PTX_FLAG": "--warn-on-spills"},
28+
)
29+
_ptx_compiler_make_errors_visible_at_exit: bool = field(
30+
default=False,
31+
metadata={"PTX_FLAG": "--make-errors-visible-at-exit"},
32+
)
1733

1834
def __post_init__(self):
1935
message = (
@@ -29,15 +45,34 @@ def __post_init__(self):
2945
case _:
3046
raise TypeCheckingError(message)
3147

32-
for field in (
48+
for field_ in (
3349
"max_blocks_per_cluster",
3450
"max_registers_per_thread",
3551
"min_blocks_per_sm",
3652
):
37-
value = getattr(self, field)
53+
value = getattr(self, field_)
3854
if value is not None and (not isinstance(value, int) or value < 0):
3955
message = (
40-
f"Expected compiler option {field} to be a "
56+
f"Expected compiler option {field_} to be a "
4157
f"positive integer but got {value}"
4258
)
4359
raise TypeCheckingError(message)
60+
61+
for field_ in fields(self):
62+
if "PTX_FLAG" not in field_.metadata:
63+
continue
64+
65+
if not isinstance(getattr(self, field_.name), bool):
66+
message = (
67+
f"Expected compiler option {field_.name} to be bool "
68+
f"but got {type(getattr(self, field_.name))}"
69+
)
70+
raise TypeCheckingError(message)
71+
72+
@property
73+
def _ptx_compiler_options(self) -> tuple[str, ...]:
74+
return tuple(
75+
field_.metadata["PTX_FLAG"]
76+
for field_ in fields(self)
77+
if "PTX_FLAG" in field_.metadata and getattr(self, field_.name)
78+
)

experimental/cuda-lang/src/cuda/lang/_execution.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,10 @@ def __init__(
138138
max_blocks_per_cluster: int | None = None,
139139
max_registers_per_thread: int | None = None,
140140
min_blocks_per_sm: int | None = None,
141+
_ptx_compiler_verbose: bool = False,
142+
_ptx_compiler_warn_on_local_memory_usage: bool = False,
143+
_ptx_compiler_warn_on_spills: bool = False,
144+
_ptx_compiler_make_errors_visible_at_exit: bool = False,
141145
):
142146
"""
143147
Args:
@@ -168,6 +172,10 @@ def __init__(
168172
max_blocks_per_cluster=max_blocks_per_cluster,
169173
max_registers_per_thread=max_registers_per_thread,
170174
min_blocks_per_sm=min_blocks_per_sm,
175+
_ptx_compiler_verbose=_ptx_compiler_verbose,
176+
_ptx_compiler_warn_on_local_memory_usage=_ptx_compiler_warn_on_local_memory_usage,
177+
_ptx_compiler_warn_on_spills=_ptx_compiler_warn_on_spills,
178+
_ptx_compiler_make_errors_visible_at_exit=_ptx_compiler_make_errors_visible_at_exit,
171179
)
172180
self._arch = arch
173181
self._gpu_name = gpu_name

experimental/cuda-lang/test/test_kernel_attributes.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from cuda.lang._exception import TypeCheckingError
77
from test.util import compile_kernel, require_hopper_or_newer
88
import pytest
9+
import torch
910

1011

1112
@require_hopper_or_newer()
@@ -20,6 +21,10 @@
2021
dict(max_threads_per_block=1.0),
2122
dict(max_registers_per_thread=1.0),
2223
dict(min_blocks_per_sm=1.0),
24+
dict(_ptx_compiler_verbose=1.0),
25+
dict(_ptx_compiler_warn_on_local_memory_usage=1.0),
26+
dict(_ptx_compiler_warn_on_spills=1.0),
27+
dict(_ptx_compiler_make_errors_visible_at_exit=1.0),
2328
),
2429
)
2530
def test_bad_kernel_attribute_types(kwarg):
@@ -119,3 +124,41 @@ def foo():
119124
CHECK-NEXT: .minnctapersm 2
120125
""",
121126
)
127+
128+
129+
@pytest.mark.parametrize(
130+
"option",
131+
(
132+
"_ptx_compiler_verbose",
133+
"_ptx_compiler_warn_on_local_memory_usage",
134+
"_ptx_compiler_warn_on_spills",
135+
"_ptx_compiler_make_errors_visible_at_exit",
136+
),
137+
)
138+
@pytest.mark.parametrize("value", (True, False))
139+
def test_ptx_compiler_accepts_all_options(option, value):
140+
@cl.kernel(**{option: value})
141+
def foo():
142+
pass
143+
144+
cl.launch(torch.cuda.current_stream(), (1,), (1,), foo, ())
145+
146+
147+
def test_ptx_compiler_verbose_stderr(capsys):
148+
@cl.kernel(_ptx_compiler_verbose=True)
149+
def foo():
150+
pass
151+
152+
cl.launch(torch.cuda.current_stream(), (1,), (1,), foo, ())
153+
outerr = capsys.readouterr()
154+
assert "ptxas info" in outerr.err
155+
156+
157+
def test_ptx_compiler_stderr_empty_when_not_verbose(capsys):
158+
@cl.kernel(_ptx_compiler_verbose=False)
159+
def foo():
160+
pass
161+
162+
cl.launch(torch.cuda.current_stream(), (1,), (1,), foo, ())
163+
outerr = capsys.readouterr()
164+
assert "ptxas info" not in outerr.err

0 commit comments

Comments
 (0)