Skip to content

Commit 1ea58d9

Browse files
Overlay fill, zeros, and ones from Base (#123)
Co-authored-by: Tim Besard <tim.besard@gmail.com>
1 parent fea7e20 commit 1ea58d9

14 files changed

Lines changed: 105 additions & 107 deletions

File tree

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,10 @@ uses standard Julia syntax and is overlaid on `Base`.
140140
### Construction
141141
| Operation | Description |
142142
|-----------|-------------|
143-
| `ct.zeros(shape, T)` | Zero-filled tile |
144-
| `ct.full(shape, value, T)` | Constant-filled tile |
145-
| `ct.arange(shape, T)` | Sequence `[1, 2, 3, ...]` |
143+
| `zeros(T, dims...)` | Zero-filled tile (Base overlay) |
144+
| `ones(T, dims...)` | One-filled tile (Base overlay) |
145+
| `fill(value, dims...)` | Constant-filled tile (Base overlay) |
146+
| `ct.arange(shape, T)` / `ct.arange(n, T)` | Sequence `[1, 2, 3, ..., n]` |
146147

147148
### Shape
148149
| Operation | Description |

examples/batchmatmul.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ function batch_matmul_kernel(A::ct.TileArray{T,3}, B::ct.TileArray{T,3}, C::ct.T
2323
num_k = cld(K, Int32(tk))
2424

2525
# Initialize accumulator with Float32 for precision
26-
acc = ct.full((tm, tn), zero(Float32), Float32)
26+
acc = zeros(Float32, tm, tn)
2727

2828
# K reduction loop
2929
k = Int32(1)

examples/layernorm.jl

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ function layer_norm_fwd(X::ct.TileArray{Float32, 2}, W::ct.TileArray{Float32, 1}
2929
N = size(X, 2)
3030

3131
# Compute mean
32-
mean = ct.full((1, TILE_N), 0.0f0, Float32)
32+
mean = zeros(Float32, (1, TILE_N))
3333
j = Int32(1)
3434
while j <= num_tiles
3535
tx = ct.load(X, (bid_m, j), (1, TILE_N); padding_mode=ct.PaddingMode.Zero)
@@ -40,12 +40,12 @@ function layer_norm_fwd(X::ct.TileArray{Float32, 2}, W::ct.TileArray{Float32, 1}
4040
ct.store(Mean, bid_m, mean)
4141

4242
# Compute variance
43-
var = ct.full((1, TILE_N), 0.0f0, Float32)
43+
var = zeros(Float32, (1, TILE_N))
4444
j = Int32(1)
4545
while j <= num_tiles
4646
tx = ct.load(X, (bid_m, j), (1, TILE_N); padding_mode=ct.PaddingMode.Zero)
4747
# Mask for valid elements
48-
mask = reshape(((j - Int32(1)) * Int32(TILE_N) .+ ct.arange((TILE_N,), Int32)) .<= N, (1, TILE_N))
48+
mask = reshape(((j - Int32(1)) * Int32(TILE_N) .+ ct.arange(TILE_N, Int32)) .<= N, (1, TILE_N))
4949
centered_tx = ifelse.(mask, tx .- mean, 0.0f0)
5050
var = var .+ (centered_tx .^ 2.0f0)
5151
j += Int32(1)
@@ -93,7 +93,7 @@ bid_m and j are 1-indexed (block ID and tile index).
9393
wdy = tw .* tdy
9494

9595
# Mask for valid elements
96-
indices = ct.arange((TILE_N,), Int32)
96+
indices = ct.arange(TILE_N, Int32)
9797
offset = (j - Int32(1)) * Int32(TILE_N)
9898
global_indices = offset .+ indices
9999
mask = reshape(global_indices .<= N, (1, TILE_N))
@@ -131,8 +131,8 @@ function layer_norm_bwd_dx(DX::ct.TileArray{Float32, 2}, DY::ct.TileArray{Float3
131131
rstd = ct.load(Rstd, bid_m, (1,); padding_mode=ct.PaddingMode.Zero)
132132

133133
# First pass: compute c1 and c2 reduction terms
134-
c1 = ct.full((1, TILE_N), 0.0f0, Float32)
135-
c2 = ct.full((1, TILE_N), 0.0f0, Float32)
134+
c1 = zeros(Float32, (1, TILE_N))
135+
c2 = zeros(Float32, (1, TILE_N))
136136
j = Int32(1)
137137
while j <= num_tiles
138138
_, xhat, wdy = bwd_helper(X, W, DY, bid_m, j, mean, rstd, TILE_N, N)
@@ -190,8 +190,8 @@ function layer_norm_bwd_dx_partial_dwdb(DX::ct.TileArray{Float32, 2}, DY::ct.Til
190190
rstd = ct.load(Rstd, bid_m, (1,); padding_mode=ct.PaddingMode.Zero)
191191

192192
# First pass: compute c1 and c2 reduction terms
193-
c1 = ct.full((1, TILE_N), 0.0f0, Float32)
194-
c2 = ct.full((1, TILE_N), 0.0f0, Float32)
193+
c1 = zeros(Float32, (1, TILE_N))
194+
c2 = zeros(Float32, (1, TILE_N))
195195
j = Int32(1)
196196
while j <= num_tiles
197197
_, xhat, wdy = bwd_helper(X, W, DY, bid_m, j, mean, rstd, TILE_N, N)
@@ -253,8 +253,8 @@ function layer_norm_bwd_dwdb(DW::ct.TileArray{Float32, 2}, DB::ct.TileArray{Floa
253253
bid_n = ct.bid(1)
254254
num_tiles = ct.num_tiles(DW, 2, (TILE_N, TILE_M))
255255

256-
dw = ct.zeros((TILE_N, TILE_M), Float32)
257-
db = ct.zeros((TILE_N, TILE_M), Float32)
256+
dw = zeros(Float32, (TILE_N, TILE_M))
257+
db = zeros(Float32, (TILE_N, TILE_M))
258258
i = Int32(1)
259259
while i <= num_tiles
260260
dw = dw .+ ct.load(DW, (bid_n, i), (TILE_N, TILE_M); padding_mode=ct.PaddingMode.Zero)

examples/matmul.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ function matmul_kernel(A::ct.TileArray{T,2}, B::ct.TileArray{T,2}, C::ct.TileArr
3939
num_k = ct.num_tiles(A, 2, (tm, tk))
4040

4141
# Initialize accumulator with Float32 for precision
42-
acc = ct.full((tm, tn), zero(Float32), Float32)
42+
acc = zeros(Float32, tm, tn)
4343

4444
# K reduction loop - accumulate partial products
4545
# NOTE: Uses while-loop pattern. Native `for k in 0:n` syntax generates complex

examples/vadd.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ function vec_add_kernel_1d_gather(a::ct.TileArray{T,1}, b::ct.TileArray{T,1}, c:
3131
tile::Int) where {T}
3232
bid = ct.bid(1)
3333
# Create index tile for this block's elements
34-
offsets = ct.arange((tile,), Int32)
34+
offsets = ct.arange(tile, Int32)
3535
base = ct.Tile((bid - Int32(1)) * Int32(tile))
3636
indices = ct.broadcast_to(base, (tile,)) .+ offsets
3737

src/compiler/intrinsics/core.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -177,9 +177,9 @@ function emit_intrinsic!(ctx::CGCtx, ::typeof(Intrinsics.constant), args)
177177

178178
# Extract shape
179179
shape = get_constant(ctx, args[1])
180-
shape isa Tuple || throw(IRError("full() shape must be a compile-time constant tuple"))
180+
shape isa Tuple || throw(IRError("fill() shape must be a compile-time constant tuple"))
181181
tile_shape = collect(Int, shape)
182-
validate_tile_shape(tile_shape, "full")
182+
validate_tile_shape(tile_shape, "fill")
183183

184184
# Extract dtype from Type{T} argument
185185
elem_type = @something get_constant(ctx, args[3]) throw(IRError("constant() requires a compile-time element type"))
@@ -188,7 +188,7 @@ function emit_intrinsic!(ctx::CGCtx, ::typeof(Intrinsics.constant), args)
188188
tile_type = tile_type!(tt, dtype, tile_shape)
189189

190190
tv = emit_value!(ctx, args[2])
191-
tv === nothing && throw(IRError("full() value must be a constant or a runtime scalar"))
191+
tv === nothing && throw(IRError("fill() value must be a constant or a runtime scalar"))
192192
if tv.constant !== nothing
193193
# Compile-time constant: use ConstantOp directly
194194
value_bytes = constant_to_bytes(something(tv.constant), elem_type)

src/language/operations.jl

Lines changed: 13 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -419,48 +419,30 @@ end
419419
Factory
420420
=============================================================================#
421421

422-
public arange, full, zeros
422+
public arange
423423

424424
"""
425425
arange(shape::NTuple{1, Int}, dtype::Type{T}) -> Tile{T, shape}
426+
arange(n::Int, dtype::Type{T}) -> Tile{T, (n,)}
426427
427-
Create a 1D tile with values [1, 2, 3, ..., shape[1]] (1-indexed).
428+
Create a 1D tile with values [1, 2, 3, ..., n] (1-indexed).
428429
429430
# Example
430431
```julia
431432
indices = ct.arange((16,), Int32) # Creates Tile with [1, 2, 3, ..., 16]
433+
indices = ct.arange(16, Int32) # Same thing, scalar form
432434
```
433435
"""
434436
@inline arange(shape::NTuple{1, Int}, ::Type{T}) where {T} =
435437
Intrinsics.iota(shape, T) .+ one(T)
438+
@inline arange(n::Int, ::Type{T}) where {T} = arange((n,), T)
436439

437-
"""
438-
full(shape::NTuple{N, Int}, value, dtype::Type{T}) -> Tile{T, shape}
439-
440-
Create a tile filled with a constant value.
441-
442-
# Example
443-
```julia
444-
ones_tile = ct.full((32, 32), 1.0f0, Float32)
445-
```
446-
"""
447-
@inline full(shape::NTuple{N, Int}, value::Tile, ::Type{T}) where {N, T} =
448-
Intrinsics.constant(shape, convert(Tile{T}, value), T)
449-
@inline full(shape::NTuple{N, Int}, value, ::Type{T}) where {N, T} =
440+
# Internal: create a tile filled with a constant value.
441+
# Used by Base.fill/zeros/ones overlays (see overlays.jl).
442+
@inline _full(value, ::Type{T}, shape::NTuple{N, Int}) where {N, T} =
450443
Intrinsics.constant(shape, Tile(T(value)), T)
451-
452-
"""
453-
zeros(shape::NTuple{N, Int}, dtype::Type{T}) -> Tile{T, shape}
454-
455-
Create a tile filled with zeros.
456-
457-
# Example
458-
```julia
459-
zeros_tile = ct.zeros((32, 32), Float32)
460-
```
461-
"""
462-
@inline zeros(shape::NTuple{N, Int}, ::Type{T}) where {N, T} =
463-
full(shape, zero(T), T)
444+
@inline _full(value::Tile, ::Type, shape::NTuple{N, Int}) where {N} =
445+
Intrinsics.constant(shape, value, eltype(value))
464446

465447
#=============================================================================
466448
Shape & DType
@@ -522,6 +504,7 @@ reshaped = reshape(tile, (2, 16)) # Shape (2, 16), still 32 elements
522504
size(tile) === shape && return tile
523505
Intrinsics.reshape(tile, shape)
524506
end
507+
@inline Base.reshape(tile::Tile{T}, dims::Int...) where {T} = reshape(tile, dims)
525508

526509
"""
527510
permutedims(tile::Tile{T, S}, perm) -> Tile{T, permuted_shape}
@@ -917,7 +900,7 @@ end
917900
@inline function _matmul(a::Tile{T1}, b::Tile, ::Val{2}) where {T1}
918901
M = size(a, 1)
919902
N = size(b, 2)
920-
acc = zeros((M, N), T1)
903+
acc = zeros(T1, (M, N))
921904
muladd(a, b, acc)
922905
end
923906

@@ -926,7 +909,7 @@ end
926909
B = max(size(a, 1), size(b, 1)) # Broadcast batch dimension
927910
M = size(a, 2)
928911
N = size(b, 3)
929-
acc = zeros((B, M, N), T1)
912+
acc = zeros(T1, (B, M, N))
930913
muladd(a, b, acc)
931914
end
932915

src/language/overlays.jl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,3 +109,17 @@ for F in Floats
109109
end
110110
end
111111
end
112+
113+
114+
#=============================================================================
115+
Tile Constructors
116+
=============================================================================#
117+
118+
# Base.fill/zeros/ones return Tiles in kernel context, matching Julia's standard API.
119+
# Marked non-foldable because they return differently-typed objects.
120+
Base.Experimental.@consistent_overlay cuTileMethodTable @inline Base.fill(v, dims::NTuple{N, Int}) where {N} =
121+
_full(v, typeof(v), dims)
122+
Base.Experimental.@consistent_overlay cuTileMethodTable @inline Base.zeros(::Type{T}, dims::NTuple{N, Int}) where {T, N} =
123+
_full(zero(T), T, dims)
124+
Base.Experimental.@consistent_overlay cuTileMethodTable @inline Base.ones(::Type{T}, dims::NTuple{N, Int}) where {T, N} =
125+
_full(one(T), T, dims)

0 commit comments

Comments
 (0)