Cloud GPU runs¶
ph.cloud submits a Simulation to a remote GPU and returns the same
RunResult structure as a local run. It ships in
the base SDK. Numerical comparisons also require matching engines and settings.
Every recipe on this page is cloud-only. The account checks and preflight are unbilled service calls. Submission is billable. Do not run these recipes without beta credentials and authorization to spend.
First build sim with the Quickstart.
Keep that construction script for later recovery. These snippets continue
in the same Python session.
Match the SDK to this guide
This guide requires photonhub 0.1.4 or later. Earlier releases lack
ph.Domain, ph.Mesh, ph.Port, ph.GaussianBeam, the *_rad angle
names, cloud wait_timeout_s, cloud submit(max_usd=...) and the
spend-safe defaults described below. Check yours with pip show photonhub
and upgrade with pip install -U photonhub. See
Install.
Getting access¶
The beta has no uninvited public signup. Request access at leapfield.ai. The SDK needs the service URL and API key issued to an authenticated beta account. An invitation code or desktop password is not an API key.
The desktop application uses a revocable session and provisions its own session-scoped cloud credential. Desktop users do not paste an API key.
Configure¶
Set the two environment variables to the values issued with your account. Replace the text in quotes before running this cloud-only setup recipe:
The client reads these automatically. To configure explicitly instead:
# CLOUD ONLY: configuration and unbilled account checks
import os
import photonhub as ph
ph.cloud.configure(
url=os.environ["PHOTONHUB_URL"],
api_key=os.environ["PHOTONHUB_API_KEY"],
request_timeout_s=30.0,
)
print(ph.cloud.whoami())
print(ph.cloud.account())
ph.cloud.reset() returns configuration to environment defaults.
request_timeout_s bounds an HTTP request. It is separate from the job wait
limit below. Keep credentials out of shared notebooks and support requests.
Choose the GPU and the solver build¶
During the closed test, every quote and run names the cloud GPU and the solver build. The GPU comes from the service's menu. The solver build is the one your closed-test guide names; replace the text in quotes:
# CLOUD ONLY, UNBILLED
print(ph.cloud.gpus())
GPU = "gpu:" + ph.cloud.gpus()[0]["id"]
SOLVER = "SOLVER_BUILD_FROM_YOUR_GUIDE"
Without them the service refuses the quote with HTTP 400, before any job exists, so nothing is charged.
Check before you submit¶
# CLOUD ONLY, UNBILLED: sim is the quickstart scene
pre = ph.cloud.preflight(sim, device=GPU, solver=SOLVER, max_usd=5.00)
print(pre.summary())
quote = ph.cloud.estimate(sim, device=GPU, solver=SOLVER)
Preflight checks device support, runnable simulation settings, the server
quote and its grid, the price limit and available funds. estimate applies
that grid check as well. A quote does not reserve capacity.
The check covers the quoted grid. The API service and the solver image are versioned separately. It does not establish numerical equivalence with your local engine. See Engine version skew.
Submit within a price limit¶
# CLOUD ONLY, BILLABLE: quotes first and refuses above the ceiling
# Choose a ceiling you are authorized to spend.
data = ph.cloud.run_quoted(sim, device=GPU, solver=SOLVER, max_usd=5.00, wait_timeout_s=300.0)
From photonhub 0.1.4, run, submit and run_quoted quote before
submission by default. They bind submission to a quote within max_usd and available funds.
The default ceiling is $5. A quote_id you already accepted can be bound as
issued. max_usd=None submits unquoted with no ceiling. These are client
controls, not a price or service-availability commitment. Check your
installed version with pip show photonhub.
For asynchronous execution:
# CLOUD ONLY, BILLABLE: keep the id before waiting
job = ph.cloud.submit(sim, device=GPU, solver=SOLVER, max_usd=5.00, wait_timeout_s=300.0)
print(job.job_id)
data = job.result()
wait_timeout_s limits the client wait. CloudJobTimeout leaves the service
job running and billing. Save the job id, then resume it or request
cancellation with job.cancel(). If the service refuses cancellation,
CloudError is raised and the job continues. A confirmed cancelled wait
raises SolverRunError. A job already finished can still return its result.
timeout is the older compatibility spelling and emits a warning.
Recover an existing job¶
Jobs survive the process that submitted them. Save the id and reuse it:
# CLOUD ONLY, UNBILLED: use an existing id, never a new submission
job = ph.cloud.resume(os.environ["PHOTONHUB_JOB_ID"], simulation=sim,
wait_timeout_s=300.0)
data = job.result()
print(data.provenance)
Set PHOTONHUB_JOB_ID to that existing id. Passing the original simulation
is especially useful from another machine. It must be the simulation that ran.
Rebuilt there from the same script it usually is: rounding is allowed for, and
launch amplitudes may differ by 0.1 %, as they can between builds of the
numerical libraries for a nearly degenerate port such as a square core. The
profile tables of a ModeSource are compared to rounding only, so entries
near a field node can be refused across machines. One
that differs further, such as a launch with a flipped sign, raises
SimulationMismatchError and names the difference, and the same script can
build a different mesh on a newer SDK. Leave simulation= out then and the
job reads with what it saved. A bundle with no sim.json is compared with the
spec this client stored at submission, so without that cache only its grid is
compared. The local result cache also stores
state needed for user-frame coordinates and port readout. Keep it intact:
on a machine without it the fields read but the ports do not come back, so
transmission raises. To read them there, build the simulation on the SDK
that ran the job and pass it.
list_jobs() and job_status(job_id) report history, state and actual cost.
If a submission fails after the request may have reached the service, inspect job history before submitting again. Submissions are not automatically retried. A second submission creates a second billable job.
Sweeps and result structure¶
ph.cloud.Batch follows the local ph.Batch
interface. They are separate classes. Likewise ph.submit starts a local
subprocess and ph.cloud.submit creates a remote job. Cloud placement and
concurrency are service-defined.
Cloud results use the local monitor names, dimensions, coordinates and
normalization attributes. Inspect data.provenance["solver_version"] and
data.provenance["git_sha"] to identify the engine that produced a result.
Match numerical settings as well before comparing physics.
Errors¶
ValueError: construction, runnable preflight or invalid client arguments. Runnable checks occur before a request to the service.SolverRunError: a simulation failed, diverged or was cancelled.CloudError: configuration, authentication, service response, transport or result-transfer failure..status_codeand.bodycan carry service detail;.job_id, when present, identifies an accepted job to resume.CloudJobTimeout: the client wait deadline expired. The job continues. HTTP request deadlines are separate; low-level timeout or I/O errors can also propagate from paths outside the cloud error wrappers.
See Troubleshooting for recovery. For beta support, contact beta@leapfield.ai.
Cost boundaries¶
Account, device, estimate, preflight, history, status and cancellation calls
are unbilled. run, submit, run_quoted and batch execution are billable.
Local CPU runs are not metered by the service.
See the full ph.cloud reference and
Known limitations.