Conversation
There was a problem hiding this comment.
Some questions added on the PR. Main confusion is around "slots" - these look sort of like memory pages, but I can't figure out why, or how the f32 / max 1024 slots limits were picked.
Another concern is perfect tiling only- with materialize in naive matmul one can launch more threads than actually write back to the output buffer (threads with indices out of range simply drop the final write value).
Is there a way to extend this to non-perfectly-tiling matmuls?
|
|
||
| The runtime allocates its storage with `cudaMallocManaged` or | ||
| `hipMallocManaged`. The resulting pointer is accessible by both host code and | ||
| GPU kernels. |
There was a problem hiding this comment.
This has changed as of #141 , we now have device-only buffers.
| ``` | ||
|
|
||
| Storage placement and lifetime can instead be determined by the operation that | ||
| creates or consumes the buffer. |
There was a problem hiding this comment.
What does it mean that 'lifetime can be determined by the operation that consumes the buffer'?
| # output-coordinate, | ||
| # inner-tile-index) | ||
| # return accumulator | ||
| (def gpu.f32.tiled-matmul.kernel : {[ |
There was a problem hiding this comment.
Does this assume perfect tiling? What would need to change to support non-perfect tiles?
| ("reduce", "reducec"), | ||
| ("materialize", "materializec"), | ||
| ( | ||
| "gpu.shared.row-major.cooperative-load", |
There was a problem hiding this comment.
This feels like a materialize; is this what you are referring to as a 'sequentialmaterialize' in PR #142 ?
| void *data; | ||
| uint64_t len; | ||
| }} catena_gpu_buf_t; | ||
| #define CATENA_GPU_MAX_SHARED_F32_SLOT_ELEMENTS 1024ULL |
There was a problem hiding this comment.
What is this?
I can't really figure out what the 'slot' abstraction is, why it's limited to 1024, f32 only, etc.
|
closing for #152 |
Summary
Preliminary Tiled Matmul implementation.
Implementation
Stateful primitives taking runtime "wire"
gpu.stategpu.shared.alloc: allocates a persistent block-local shared-memory slot and returns its identity, updated proof state, and slot value.gpu.shared.row-major.cooperative-load: cooperatively loads a logical 2D view into a row-major shared slot, with each block thread loading one element.gpu.sync: synchronizes all threads in the block.gpu.shared.materialize: exposes a synchronized, ready shared slot as a borrowed buffer.gpu.stateis an erased, linear description of the block’s execution history.Each stateful primitive consumes the current state and produces a new state whose event records what happened:
Operations requiring a particular slot condition also consume a proof tied to that exact state:
allocated-at(slot, state).ready-at(slot, state).Because the state is linear, operations cannot independently reuse an obsolete execution history. Because proofs mention both the slot identity and state event, a proof for one slot or an earlier state cannot justify access to another slot or later occurrence.
This is intended to prevent:
Both states and proofs are compile-time objects and are erased before GPU code generation. Currently,
admit-allocated-at,admit-ready-at, and keyed-state operations are temporary axioms. Therefore, the types express the intended safety conditions, but full safety is not yet guaranteed: it will require deriving these proofs from allocation, loading, and synchronization events rather than admitting them.Next
materializelaunches a kernel, imo it is wrong, onlygpu.materializeshould launch kernels. Hence, we need to change the implementation ofmateralizeand rewrite tests usinggpu.materializesyncshould be changed to accept a closure corresponding to a phase. The reason is that we don't want phase "state" to escape the sync.