Skip to content

refactor: ADR-019 — remove GPU knowledge from core tensor (#126) - #149

Merged
kolkov merged 8 commits into
mainfrom
refactor/adr-019-opaque-backend-data
Aug 4, 2026
Merged

kolkov merged 8 commits into
mainfrom
refactor/adr-019-opaque-backend-data

Conversation

@kolkov

@kolkov kolkov commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements ADR-019 across 5 phases — removes all GPU-specific code from internal/tensor/, making it fully backend-agnostic.

Phase 1: backendData any + Materialize

  • Opaque backendData any field on RawTensor
  • Materialize(t *RawTensor) ([]byte, error) on Backend interface

Phase 2: Materializer + new Data() path

  • Materializer interface for lazy GPU readback
  • Data() uses Materializer when set, legacy path as fallback

Phase 3: BackendReleaser + caller migration

  • BackendReleaser interface (ReleaseBackendData, SetPersistent, IsPersistent)
  • 35 callers in autodiff, optim, nn, models migrated

Phase 4: Delete legacy GPU code

  • lazy_gpu.go and lazy_gpu_wasm.go deleted from internal/tensor/
  • LazyGPUData moved to internal/backend/webgpu/
  • Legacy fields/methods removed from RawTensor (gpuData, GPUData, ReleaseGPU, etc.)
  • All dual-write legacy calls removed

Phase 5: Remove SIMD from tensor

  • 5 vendored sigmoid SIMD files deleted (cpu backend already has goexperiment.simd version)
  • internal/tensor/ now has zero //go:build tags

Also included

  • All timing-dependent WebGPU test assertions eliminated (6 flaky removed, 6 correctness checks added)

Results

  • internal/tensor/: zero build tags, zero platform-specific files, zero GPU knowledge
  • WASM builds without stubs
  • 22/22 test packages pass
  • Lint: 0 issues
  • Net line reduction across all phases

Test plan

  • go build ./...
  • GOOS=js GOARCH=wasm go build ./...
  • go test -short ./... — 22 packages, 0 failures
  • go vet ./...
  • golangci-lint run — 0 issues

kolkov added 8 commits August 4, 2026 10:17
…terface (ADR-019 Phase 1)

Add opaque backendData any field to RawTensor with BackendData/SetBackendData
accessors. Add Materialize method to Backend interface — CPU returns buffer
directly, WebGPU triggers GPU readback, Autodiff delegates to inner backend.

Purely additive — no existing fields or behavior removed. Phase 2 will migrate
Data() to use Materialize; Phase 4 will remove legacy GPU fields.
Data() now checks for a Materializer before falling back to the legacy
gpuData.Realize() path. WebGPU createLazyResult sets both SetBackendData
and SetMaterializer so the new path triggers first.

After materialization, backendData and materializer are cleared to prevent
double-realization. Legacy GPU path is preserved for Phase 3-4 callers.
Remove 6 flaky pre-readback assertions (activeBatchCount, IsRealized)
that tested internal GPU state and raced under load. Replace with
numerical correctness checks — tests now verify computed values, not
implementation details. Post-readback drain checks (count == 0) kept
as valid contract assertions.
…9 Phase 3)

Add BackendReleaser interface with ReleaseBackendData, SetPersistent,
IsPersistent. Implemented on all backends (CPU=no-op, WebGPU=delegates
to LazyGPUData, Autodiff=delegates to inner).

Migrate 35 callers in autodiff tape/backward, optim adam/sgd,
nn.Parameter, and models/llama to dual-write: new BackendReleaser
path + legacy ReleaseGPU/SetGPUPersistent preserved for Phase 4.
Delete lazy_gpu.go and lazy_gpu_wasm.go from internal/tensor/.
Move LazyGPUData to internal/backend/webgpu/lazy_gpu_data.go.
Remove gpuData/gpuPersistDefer fields and GPUData/SetGPUData/ReleaseGPU/
SetGPUPersistent/IsLazy methods from RawTensor.

Remove all legacy dual-write calls from autodiff, optim, nn, and models.
Data() now uses only the Materializer path for GPU readback.

internal/tensor/ has zero build tags, zero GPU knowledge, zero WASM stubs.
20 files changed, -534 lines net reduction.
Delete 5 sigmoid SIMD files from internal/tensor/ (vendored AVX2 kernel
predating the cpu backend's SIMD infrastructure). Tensor Sigmoid/SiLU
now use scalar loops — the cpu backend's goexperiment.simd kernel handles
all training workloads.

internal/tensor/ now has zero //go:build tags, zero platform-specific
files, zero GPU knowledge. ADR-019 is complete.
@kolkov
kolkov merged commit c0df9ca into main Aug 4, 2026
11 checks passed
@kolkov
kolkov deleted the refactor/adr-019-opaque-backend-data branch August 4, 2026 09:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant