A HIP lane: ! on AMD GPUs (for the hip branch, #891) - #958
Merged
Merged
Conversation
…rpus (bendlang#891) HIPRTC compiles the CUDA lane's device code as written. It defines __HIPCC_RTC__, so BEND_RTC replaces the six __CUDACC_RTC__ tests, and it ignores -default-device, so force_cuda_host_device stands in. The host side is a BEND_HIP block beside BEND_CUDA; main.ts builds with it when there is no CUDA and ROCm is at $ROCM_PATH, else /opt/rocm. A consumer Radeon has no migrating managed memory (a managed block is pinned host memory read over PCIe: queens 47 s), so the corpus is host memory with a twin in VRAM that a ! copies in and out: every Loc is an index, and the host never runs during a device turn. The twin's heap is lazy, 2 MB chunks under mprotect: after a turn a chunk is downloaded on its first host touch, and the next turn uploads only the chunks the host touched. The handler is chained in front of err_trap in pool_stack. tests/run/gpu_turns pins three ! turns with the host rebuilding a device-built tree between them. gpu_hash, the same in both RTC lanes, moves above them. The comp.ts cap goes to 70000 on this branch (an estimate: about 68100 ttok). On an RX 7800 XT (ROCm 7.2.1, WSL2): the 20 runnable ! tests print the CPU lane's bytes, and the lane beats 16 threads on 11 of the 16 runtime benches. Not run: the gates, CUDA, Metal, native Linux. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018yDkB3RYnpnX3x1Uf12tEW
costamatheus97
force-pushed
the
hip-lane
branch
from
September 21, 2026 11:49
7ab5eab to
2ba2bd1
Compare
Contributor
|
Thank you, and welcome to the repo as the keeper of this lane. The The arrangement, so it is written down:
The benchmark table is impressive, and the memfd-plus-mprotect lazy heap is a clean way to live without managed memory. Note: this reply was written by an AI after it reported the PR to me and I made the decision. If anything here is wrong, reply and I will review it myself. |
costamatheus97
added a commit
to costamatheus97/bend
that referenced
this pull request
Sep 21, 2026
…ve the lanes Two behaviour-neutral pieces of the HIP lane (bendlang#958, on `hip`) that do not depend on it, as offered there. BEND_RTC is defined when the file is compiled by the device's runtime compiler, and the six `__CUDACC_RTC__` tests read it. A second RTC lane then adds its macro to one definition and leaves the six sites alone. gpu_hash moves out of the CUDA block to just above the lane blocks, under `#if BEND_CUDA`. It reads only BEND_SRC and CUBE_LOG, so a lane that keeps a `.gpu` cache can share it by widening that one guard. With both on main, `hip` differs from main in shared code by `|| defined(__HIPCC_RTC__)` and `|| BEND_HIP` on those two lines.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
An AMD lane for
!, through HIP and HIPRTC, as discussed in #891. This is for thehipbranch, notmain. That branch does not exist yet, so the PR points atmainfor now and I will retarget it oncehipis created. One commit onmainat e52cda4 (2.0.24).Tested on one card: Radeon RX 7800 XT (gfx1101, 16 GB), ROCm 7.2.1, WSL2. I have no CUDA or Metal hardware.
What it changes
main.ts: without CUDA, a!program builds with-DBEND_HIP=1when ROCm is at$ROCM_PATH, else/opt/rocm.comp.ts, device code: HIPRTC compiles the CUDA lane's device code as written. It defines__HIPCC_RTC__, so oneBEND_RTCmacro replaces the six__CUDACC_RTC__tests. It ignores-default-device, so#pragma clang force_cuda_host_device beginstands in.comp.ts, host code: aBEND_HIPblock besideBEND_CUDA, with the same hash-keyed.gpucache.gpu_hashwas identical in both lanes, so it moved above them.tests/run/gpu_turns.bend: three!turns with the host rebuilding and extending a device-built tree between them. It passes on every lane; a lane that misses a page gets it wrong.gates/repo.tsandAGENTS.md: the cap (below) and the word "HIP" in the runtime list.What it touches outside
BEND_HIP: the six__CUDACC_RTC__tests, the move ofgpu_hash, and two macros aroundcube_runincorpus_evalthat are empty on the other lanes.Why the HIP block is larger than CUDA's
The host block is 247 lines; CUDA's is 126 and Metal's 99.
About 120 of the 247 mirror CUDA one to one: probe, compile, cache load, launch, pass. The other 125 exist because a consumer Radeon has no shared or migrating memory. It reports
concurrentManagedAccess = 0: a managed block is pinned host memory that the device reads over PCIe. The lanes keep their stacks, rings and free lists there, so queens takes 47 s.So the corpus is host memory with a twin in VRAM, which a
!copies in and out. This is legal because everyLocis an index and the host never runs during a device turn. The 125 lines are:memfdmapped twicegpu_copy,gpu_syncgpu_rings!gpu_heap,gpu_fault,gpu_trapmprotect. After a turn every chunk under the bump traps; the first host touch downloads that chunk and marks it dirty, and the next!uploads only dirty chunks. The handler is chained in front oferr_trapinpool_stackTracking by the bump alone is unsound:
heap_freeandheap_allocrewrite freed slots under it.The alternative is a twin that copies everything under the bump both ways on each
!: about 30 lines, for a lane of about 160. I measured it. On the large-heap programs it is 2 to 3 times slower (tree-radix 0.55 → 1.4 s, hashmap 0.7 → 1.1 s, tree-matmul 0.5 → 0.8 s; tree-radix moves 3.7 GB instead of 17 MB), and the lane goes from beating 16 threads on 11 of 16 benches to 7. I kept the fast version. The 125 lines are one contiguous block, so they can be cut to the simple version later without touching the rest.The code comments keep only the invariants an edit must respect; the reasoning is here and in the commit message. There is one memory model for every AMD device. An APU would copy more than it needs to, but stays correct.
The
comp.tscap: 65000 → 70000comp.tsis at 64936 ttok onmain, 64 under its cap, so any lane needs the cap raised. This commit adds 9.5 KB to the file. At the file's own bytes-per-token ratio that is about 3200 ttok, for a total near 68100. That is an estimate: I do not havettokon this machine. 70000 is the next round number; set it to the measured count if you prefer a tight cap. The change is on this branch only.Checks
gates/test.ts's rules: 1410 / 1413 with the patch and 1409 / 1412 without (the new test is the difference). The failures are the same:gfx_clicks,gfx_window,io_audio_open, which need a display or an audio device. I leftio_tcp_send_slow_peerout of both runs; it hangs under WSL on unpatchedmain.!tests print the same bytes as the CPU lane.--gpu onfails with its message when no device is visible, and the HIP log shows the kernel launches.--gpu 440MBreports in 0.14 s.bench/runtime/, perf.ts spans, wall seconds, median of 3 runs, all 16 checksums equal on both lanes:Known limits
hipMemcpyfrom SIGSEGV. The fault can only come from Bend's own evaluation code, never from inside ROCm, but POSIX does not promise it.memfd, so it gets no transparent huge pages.--gpu 2GBfor more), not taken from free VRAM.effs/window_frame.cstill has only its CUDA device path; a HIP build fills pixels on the host.$PATHfull of Windows directories. Run with a shortPATHthere; the numbers above were.