Skip to content

Commit 17524d6

Browse files
[lang] Support replacing vector elements
Signed-off-by: Asher Mancinelli <amancinelli@nvidia.com>
1 parent 1c68273 commit 17524d6

3 files changed

Lines changed: 53 additions & 16 deletions

File tree

‎experimental/cuda-lang/src/cuda/lang/_ir/op_impl/vector_impl.py‎

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
require_dtype_spec,
1010
)
1111
from cuda.tile._ir.cast_ops import implicit_cast
12+
from cuda.tile._ir.core_ops import bind_method
1213
from cuda.tile._ir.ops import strictly_typed_const
1314
from cuda.tile._ir.ops_utils import promote_dtypes
1415
from cuda.tile._ir.type import LooselyTypedScalar
@@ -35,7 +36,7 @@ def vector_undef(res_type: Type):
3536
)
3637

3738

38-
def vector_setitem(vector: Var[VectorTy], key: int | Var[ScalarTy], value: Var[ScalarTy]):
39+
def vector_with_item(vector: Var[VectorTy], key: int | Var[ScalarTy], value: Var[ScalarTy]):
3940
ty = require_vector_type(vector)
4041
if isinstance(key, int):
4142
key = strictly_typed_const(key, ScalarTy(datatype.int32))
@@ -101,7 +102,7 @@ def vector_constructor_impl(elements: tuple[Var, ...], dtype: Var) -> Var[Vector
101102
res = vector_undef(VectorTy(element_dtype, len(elements)))
102103
for index, element in enumerate(elements):
103104
value = implicit_cast(element, element_dtype, f"Vector() element {index}")
104-
res = vector_setitem(res, index, value)
105+
res = vector_with_item(res, index, value)
105106
return res
106107

107108

@@ -130,20 +131,31 @@ def apply_one(i: int):
130131
)
131132

132133
res = vector_undef(VectorTy(element_type.dtype, length))
133-
res = vector_setitem(res, 0, first_element)
134+
res = vector_with_item(res, 0, first_element)
134135
for i in range(1, length):
135136
element = apply_one(i)
136-
res = vector_setitem(res, i, element)
137+
res = vector_with_item(res, i, element)
137138

138139
return res
139140

140141

141-
# the user can't call __setitem__ in kernel code because the semantics might be
142-
# confusing. We could expose an insertelement-like operation that maps to the
143-
# vector_setitem utility though.
144142
@impl(operator.setitem, overload=(VectorTy, WILDCARD, WILDCARD))
145143
def vector_setitem_impl(object: Var[VectorTy], key: Var, value: Var):
146-
raise TypeCheckingError("Vectors are immutable: item assignment is not supported")
144+
raise TypeCheckingError(
145+
"Vectors are immutable. Consider calling vector.with_item() instead"
146+
)
147+
148+
149+
@impl(getattr, overload=(VectorTy, "with_item"))
150+
def getattr_vector_with_item(object: Var[VectorTy], name: Var):
151+
return bind_method(object, Vector.with_item)
152+
153+
154+
@impl(Vector.with_item)
155+
def vector_with_item_impl(
156+
self: Var[VectorTy], index: Var[ScalarTy], value: Var[ScalarTy]
157+
) -> Var[VectorTy]:
158+
return vector_with_item(self, index, value)
147159

148160

149161
@impl(operator.getitem, overload=(VectorTy, WILDCARD))

‎experimental/cuda-lang/src/cuda/lang/_stub/types.py‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,18 @@ def __getitem__(self, item): ...
131131
@stub
132132
def __setitem__(self, key, value): ...
133133

134+
@stub
135+
def with_item(self, index: int, value: T) -> "Vector[T]":
136+
"""Return a new vector with one element replaced.
137+
138+
Vectors have value semantics, so this operation does not modify the
139+
original vector. ``index`` must select an element of the vector.
140+
141+
Args:
142+
index: Index in vector to replace.
143+
value: New value.
144+
"""
145+
134146

135147
class Pointer(Generic[T]):
136148
"""Typed address into a CUDA memory space with low-level load and store operations."""

‎experimental/cuda-lang/test/test_vectors.py‎

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#
33
# SPDX-License-Identifier: Apache-2.0
44

5+
from test.util import compile_kernel
56
import operator
67

78
import pytest
@@ -399,16 +400,28 @@ def kernel(tensor):
399400

400401

401402
def test_vector_setitem():
402-
@cl.kernel
403403
def kernel():
404-
with cl.local_array(4, cl.int32) as arr:
405-
v = arr.get_base_pointer().load(count=4)
406-
v[0] = 1
404+
v = cl.shared_array(1, cl.int8).get_base_pointer().load(count=2)
405+
v[0] = 1
407406

408-
with pytest.raises(
409-
TypeCheckingError, match="Vectors are immutable: item assignment is not supported"
410-
):
411-
cl.compile_simt(kernel, [KernelSignature([])])
407+
compile_kernel(
408+
kernel,
409+
raises=pytest.raises(TypeCheckingError, match="Vectors are immutable"),
410+
)
411+
412+
413+
def test_vector_with_item():
414+
@cl.kernel
415+
def kernel(original, updated):
416+
original_vector = original.get_base_pointer().load(count=4, alignment=16)
417+
updated_vector = original_vector.with_item(2, 42)
418+
updated.get_base_pointer().store(updated_vector, alignment=16)
419+
420+
a = torch.arange(4, dtype=torch.int32, device="cuda")
421+
b = torch.arange(4, dtype=torch.int32, device="cuda")
422+
cl.launch(torch.cuda.current_stream(), (1,), (1,), kernel, (a, b))
423+
assert a.cpu().tolist() == [0, 1, 2, 3]
424+
assert b.cpu().tolist() == [0, 1, 42, 3]
412425

413426

414427
def test_vector_from_tuple():

0 commit comments

Comments
 (0)