Parallel execution and restartable workflows
Schemaxis can now schedule independent native jobs concurrently, reserve resources, retry incomplete jobs, and render groups of views from a previously prepared Blender scene. Legacy workflows without execution settings keep their serial schedule. Native objects remain process-local. Only verified files cross job boundaries.
Start with a bounded allocation#
{
"version": "schemaxis.workflow/1",
"execution": {"maxWorkers": 2, "cpus": 4, "memoryMB": 4096, "gpus": 1},
"operations": [
{
"id": "surfaces",
"execution": {"threads": 2, "memoryMB": 1024, "timeChunkSize": 2},
"document": {"version": "schemaxis/1", "times": [0, 1, 2, 3], "nodes": [], "scenes": []}
}
]
}
The empty nodes/scenes above are placeholders. Runnable examples are parallel-timesteps.json, blender-render-groups.json, and mpi-sphere-slice.json. A complete CFD volume/slice/reduction and file-handoff example is foam-native-parallel.json.
The coordinator starts a job when every referenced producer operation has verified all its batches and the job fits the remaining resource budget. Unrelated operations can overlap. References still point to earlier operations in the authored list; that list is a valid topological ordering, not a mandatory serial execution order. The coordinator records results in planned order regardless of completion order.
Global execution settings:
| Setting | Default | Meaning |
|---|---|---|
maxWorkers |
1 | Maximum concurrent native jobs |
cpus |
Host logical CPU count | Shared CPU-slot budget |
memoryMB |
8192 | Shared declared RAM budget |
gpus |
1 | GPU render slots; currently only 0 or 1 is supported |
Operation execution settings:
| Setting | Default | Meaning |
|---|---|---|
threads |
1 for ParaView; Blender render threads otherwise | Threads per MPI rank or Blender process |
ranks |
1 | ParaView MPI ranks; reservation is ranks × threads |
mpiexec |
None | Required absolute launcher path when ranks > 1 |
memoryMB |
1024 | Reservation for the entire job, including all ranks |
gpus |
1 for CUDA/OPTIX, otherwise 0 | Exclusive GPU slot reservation |
timeChunkSize |
No splitting | Number of explicit timesteps per independent batch |
RAM reservations are estimates used for admission, not OS-enforced limits. Set them
from measured memory consumption, with headroom for the OS and other applications.
Thread settings constrain common OpenMP, BLAS and VTK pools; they are not CPU affinity
or cgroup limits. Blender's reservation must match render.threads. The single GPU
slot prevents simultaneous renders competing for the same device; multi-GPU device
assignment and cluster scheduling remain future work.
Batches, identities and limits#
Time batching requires a finite, explicit times list. Each contiguous batch keeps
the full analytic parameter sweep and native object reuse within its own process.
The original unsplit expansion/publication budgets are checked before splitting.
Automatic source-time discovery and splitting an analytic axis are not supported by
this first batching contract. Use separate operations for independent parameter
sets, or keep the analytic sweep together when reuse is valuable.
Jobs have stable identities operation/batch, with original timeIndices recorded
alongside each batch. Native state indices and object identities are local to that
batch. Artifacts are concatenated in batch order, so $artifact indices do not
change with completion order. Every artifact is checked for exact planned membership;
missing or duplicate jobs fail verification. A downstream operation currently waits
for the producer's entire operation, not individual early artifacts.
Restart and cancellation#
PYTHONPATH=src python3 -m schemaxis run examples/schemaxis/parallel-timesteps.json \
--paraview-root /path/to/paraview --output-directory evidence/parallel-run
PYTHONPATH=src python3 -m schemaxis run examples/schemaxis/parallel-timesteps.json \
--paraview-root /path/to/paraview --output-directory evidence/parallel-run --resume
PYTHONPATH=src python3 -m schemaxis verify evidence/parallel-run
Resume requires the unchanged authored workflow. Completed attempts are reused only after native receipt/artifact verification, authored-plan checks, dependency checks and available input fingerprints. Generated geometry is reusable. Blender's explicit glTF and blend inputs are fingerprinted. ParaView external readers conservatively rerun because an individual filename does not describe all case files, companion files or resources. This is deliberately not a general dependency cache.
Every attempt gets a new directory such as surfaces/batch-0/attempt-0002. Earlier
attempts remain for diagnosis. A process or file existing is never enough to reuse
an attempt: it needs a complete verified job receipt. Successful jobs retain the
runtime archive that actually produced them, so a resumed workflow may contain
verified attempts from different runtime snapshots.
On a job failure, the coordinator stops admitting jobs and cancels active siblings. Native execution uses isolated process groups; cancellation and timeout terminate those groups and tracked local descendants, including MPI workers that create separate process groups. Linux process birth times protect against PID reuse. Completed verified attempts are retained. Ctrl-C follows the same cleanup path. The coordinator holds a filesystem lock to prevent two resumptions writing the same workflow simultaneously. Version probing uses the existing separately bounded interpreter probe and can delay cancellation during startup; remote MPI process cleanup is not qualified.
Blender: prepare once, render view groups#
Set scenes[0].prepareOnly to true in an ordinary Blender document. It still needs
one camera writer to establish the saved camera, but publishes only the saved scenes
and performs the normal fresh-process scene reopening check.
Then reference a scene from a render operation:
{
"id": "front",
"document": {
"version": "schemaxis.blender.render/1",
"sceneFile": {"$artifact": "prepare", "index": 0},
"render": {"threads": 2, "samples": 16},
"size": [320, 240],
"cameras": [{"direction": [1, -2, 1]}]
}
}
Several render operations can share that source. Each opens a retained local scene copy, configures lighting/render settings, renders its camera group and checks that geometry/material snapshots remain unchanged. Images are decoded natively and their hashes, dimensions and camera state are checked. Source digests are checked again on verification/resume. Scene loading disables Python auto-execution. Inputs must be Schemaxis scenes containing metadata and self-contained assets; linked libraries and unpacked external images are rejected. Existing scenes created before metadata support must be prepared again. Saved-scene cameras are literal, not analytic markers.
Discover the contract with schemaxis query, schemaxis plan, or
schemaxis schema --section saved-scene-render. A generated schema is retained as
blender-render.schema.json.
MPI qualification boundary#
MPI uses mpiexec -n N pvbatch, with one Python driver, never --symmetric.
Select the launcher matching the ParaView build's MPI installation. The native
controller's process count must match the requested rank count and is recorded in
the receipt. Resources account for ranks multiplied by per-rank threads.
The qualified operation subset is sphere, slice, foam, merge, calculator,
surface, outline, integrate, readParallelPolyData and
readParallelUnstructuredGrid. Adaptor capability discovery reports this policy;
the generic scheduler does not need to know ParaView filter names. Other operations,
explicit export writers, glTF publication and global tuple sampling are rejected
before MPI dispatch. Serial operation remains available.
ParaView owns mesh partitioning, filter execution, reductions and rendering.
Geometry uses native parallel XML writers (.pvtp/.pvtu with their piece files).
Schemaxis never gathers the full MPI mesh for publication. Each rank fingerprints
its coordinates, topology and point/cell/field arrays in bounded chunks. Only compact
fingerprint records return to the driver. Native readback must reproduce every
nonempty piece exactly; whole pieces may move between ranks. Arbitrary repartitioning
is not covered by this verification contract. Empty ranks are allowed but every rank
must report. Companion-file manifests cover the entire referenced file closure;
verification streams hashes and rejects missing, changed or escaping files.
MPI measurement tables must target integrate outputs. Native ParaView computes
the global reduction; Schemaxis collects only the resulting scalar records and
checks the CSV against rank evidence. It does not fetch backing geometry arrays.
Downstream operations can reopen the parallel XML artifact with the corresponding
parallel reader. Metadata and every piece must remain together on a filesystem
accessible to all ranks. This is qualified locally; pvserver, remote launch,
cluster scheduling and arbitrary filters have not been qualified.
Reproduce the local tutorial qualification with explicit paths:
PYTHONPATH=src python3 tools/qualify_cfd_parallel.py \
--case /path/to/coupe_AMI.foam --paraview-root /path/to/paraview \
--mpiexec /path/to/matching/mpiexec --ranks 2 \
--output-directory evidence/cfd-qualification
The case must be decomposed. The example camera targets the vehicle tutorial; adapt its framing and colour range for other cases. Source-time discovery works within a native job; automatic source-time splitting into independent jobs remains unsupported.
Measurements and acceptance#
Every native dispatch retains full stdout/stderr logs and a metrics JSON file with elapsed time, command, reservation and sampled aggregate process-tree RSS, plus process-group RSS for compatibility. Tracking includes local MPI workers outside the launcher process group. RSS is Linux-specific, includes shared pages more than once, and can miss short peaks. It is a diagnostic measurement, not an exact physical-memory high-water mark. Native receipts include apply/publication timings for ParaView and geometry/render/ save timings for Blender. Saved-scene renders separate load and render time.
tools/qualify_parallel_execution.py runs alternating serial/parallel benchmarks,
checks exact geometry hashes and observations, deliberately fails a worker after
native execution, then checks verified reuse and retained retry attempts. On this
machine, the first qualification measured a 1.51× median speedup (15.41 s → 10.19 s)
for five small geometry jobs. This demonstrates scheduler throughput, with startup
cost prominent; it does not predict scaling for large CFD cases or GPU rendering.
The 004 CFD tutorial qualification used 1,234,240 cells across two ranks. Native distributed volume and slice readback passed, and a downstream operation reopened the volume and reproduced its integrals. Serial/MPI integrals agreed within relative 1e-8 and absolute 1e-7 tolerance. Two source-selected timesteps (0.8 and 1.0) also passed. The full suite passed 375 tests. See the retained qualification summary. These timings are not an equal-work speedup benchmark: serial omits full-volume publication. Sampled aggregate RSS was about 1.98 GB for MPI and 1.44 GB for serial; shared pages may be counted repeatedly. MPI shared-memory windows are not added by Schemaxis; native applications retain ownership of their memory layout.
The execution model is local and bounded. Future steps are broader case-specific MPI qualification, manifests for external input reuse, richer state partitioning, per-artifact readiness, explicit multi-GPU placement and remote dispatch.