← ApertureLab

Cloud GPU processing of SAS scenes

A scene covering six thousand square meters of seafloor at 2.5 cm pixels is simulated and beamformed on a cloud GPU instance in under ten minutes, for about a dime. The scene YAML that renders on a workstation runs unchanged on self-managing spot instances, one machine per scene, so a ten-scene set finishes in roughly the time of one.

Measurements

Time and cost per scene

The unit of work is a complete scene, simulated and beamformed at production fidelity.

61 m × 100 m
scene footprint at 2.5 cm pixel resolution: 150 million scatterers focused into a 9.8 megapixel image.
9.5 min
wall clock per scene, submit to delivered product, including code upload and instance boot. Scenes run on parallel machines, so a whole batch finishes in roughly the time of one.
0.13 hr
billed instance time for that scene, which is $0.10 at the on-demand rate; these runs use spot capacity, which costs less.

Measured 2026-10-10 on one scene: 61 m along track by 100 m in range, 2.5 cm pixels, point-scatterer backend at 20,000 scatterers per square meter, on a g6.xlarge spot instance, delivered as a 4000 by 2449 pixel image. Of the 9.5 minutes, simulation took 158 s and beamforming 18 s. The same scene on the Fourier-wavefield backend took 7.1 minutes and 0.09 instance-hours; its cost does not grow with scatterer density. Numbers on this page are single measurements from one run, not modeled estimates.

Mechanism

Batch execution

One command submits a batch: python -m cloud run <scene>.yaml; the Run on AWS button in the GUI does the same. Code is uploaded content-addressed, so a given version uploads once rather than once per job. Submitting fifty scenes therefore moves fifty small scene files and no redundant copies of the codebase. Each job then proceeds independently.

  1. Launch

    Each job gets its own spot GPU instance. A launch loop fills the available quota slots and searches availability zones for spot capacity, cheapest zone first. It retries transient capacity shortages indefinitely, so a batch submitted when no capacity is available waits and fills as capacity appears.

  2. Boot

    The instance starts its startup script about 30 seconds after the launch request, fetches and unpacks the content-addressed code snapshot for the submitted version in 9 seconds, and pulls the worker container, which took 2.2 minutes in the measured run. A prebaked machine image that already holds the container removes the pull.

  3. Simulate and beamform

    The full pipeline runs on the instance's GPU: acoustic simulation to complex IQ, then time-domain back-projection to a focused, georeferenced image, identical to a local run of the same scene file.

  4. Deliver and terminate

    Products upload to S3, and the instance terminates itself. Results stream back to the CLI or GUI as they do for a local run, and closing the GUI does not stop the job.

Every image carries its provenance in a watermark that records the instance type and whether it ran on spot or on-demand capacity. Cloud-generated imagery is therefore identifiable as such and traceable to the hardware that produced it.

Setup

Account setup

Setup is a single idempotent command: python -m cloud init creates the storage bucket, the worker role, and the network configuration in the user's own AWS account. Every resource is tagged so it can be found and removed as a unit. The worker container image is public. A scene then runs from one CLI command or from the Run on AWS button next to Run in the GUI. Its progress, logs, and products appear in the same panels as a local run.

Monitoring

Job and cost monitoring

The cloud path measures and bounds cost at every step. Each job reports a live cost estimate, each launch is checked against a spend ceiling, and each instance has a hard lifetime.

The AWS tab in the workbench: a job list with per-job status and live cost estimates, and a month-to-date account spend readout behind a Refresh button

The AWS tab in the workbench: per-job status and live cost estimates while jobs run, with month-to-date billed spend behind a Refresh button.

A bounded, measured cost per scene is a precondition for generating synthetic SAS data in the volume that model training requires.

Architecture

One GPU job per scene

The batch uses no scheduler in the usual sense. A scene set is split across as many instances as there are quota slots; each instance takes exactly one scene and terminates itself when its products are uploaded.

A four-step panel: design a scene in the browser, fan the scene set out to a queue, simulate at scale with one GPU per scene, and deliver one labeled dataset

The four steps are design, fan-out, simulation, and delivery. Because each scene is one GPU job, a hundred scenes finish in about the time of one.

Preflight

Local heightmap preflight

Before a batch launches, the scene's heightmap renders locally in about 30 seconds at no cost. It shows seafloor zones, ripple fields, and object placement on the geometry the simulator will trace. Once the heightmap is approved, the cloud run produces the SAS image. Each of the six tiles below crossfades between one seafloor type's local heightmap preflight and its cloud-rendered SAS image. The geometry is identical, so the two images fade into alignment.

Cloud-rendered SAS image of a flat sand seafloor Local heightmap preflight of the same flat sand scene Sand
Cloud-rendered SAS image of a fine-rippled sand seafloor Local heightmap preflight of the same fine-ripple scene Fine ripple
Cloud-rendered SAS image of a coarse-rippled sand seafloor Local heightmap preflight of the same coarse-ripple scene Coarse ripple
Cloud-rendered SAS image of a smooth mud seafloor Local heightmap preflight of the same mud scene Mud
Cloud-rendered SAS image of a fractal-relief seafloor Local heightmap preflight of the same fractal-relief scene Fractal
Cloud-rendered SAS image of a rocky seafloor Local heightmap preflight of the same rocky scene Rocky

Six seafloor types, each checked as a 30-second local heightmap at no cost before a cloud render of about ten minutes. Pixel registration between each heightmap and its SAS image is exact.