During a drag the render loop skipped a render until 0.9 x the usual
iteration time had passed since last_render_t, and last_render_t was
stamped when a render finished. A new render therefore started every
(render time + 0.9 x iteration time), about half the image rate the FPS
readout shows: at Max W 960 on ZeroGPU one image per ~100 ms instead of
~52 ms. Stamp last_render_t when the render starts.
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Also repair dynamo's stale CUDA interface in ZeroGPU workers
With the handler assertion out of the way, torch.compile got as far as
inductor's autotuner and failed with "Both events must be completed before
calculating elapsed time". torch._dynamo.device_interface.CudaInterface
copies torch.cuda functions when it is imported; the app imports it in the
main process, where ZeroGPU has swapped in CPU-side dummies, so the worker
kept a no-op synchronize and timed CUDA events that had not finished.
Rebind those copies to the real torch.cuda functions in the worker, next
to the earlier fix, and log what was repaired.
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Fix torch.compile AssertionError in ZeroGPU workers on torch 2.13
Rebuilding the Space picked up torch 2.13.0 from the ZeroGPU base image.
In a GPU worker, spaces 0.51.3 restores torch.cuda._maybe_exchange_device
to the _exchange_device builtin; torch 2.13's dynamo registers one handler
per function and fails on the duplicate ("Handler already registered for
<built-in function _cuda_exchangeDevice>"), so every viewer session died
during renderer warm-up.
Restore the real builtin at the start of both @spaces.GPU functions,
before anything compiles. No-op when the two are already distinct.
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>