Persistent Client Mode¶
Persistent Client Mode enables a single long-running client process to execute multiple simulations sequentially without terminating. This differs from Legacy Mode, where each simulation spawns a new client process that terminates after completion.
In Legacy Mode, the server repeatedly submits new client scripts (via SLURM or job scheduler) for each simulation. This introduces overhead:
- Process startup/teardown cost per simulation
- Reinitialization of data structures
- Potential delays between simulation completions and next job submission
Persistent Client Mode eliminates this overhead by maintaining a single client process in a fetch loop, allowing the server to dynamically assign simulations without spawning new processes.
Activate persistent client mode by setting:
Architecture¶
Client-Server Communication Pattern¶
Persistent clients follow a request-response fetch loop architecture:
-
Initialization Phase (once):
- Client calls
melissa_init()to register fields and establish server connection - Client receives server configuration (memmap path, port mapping)
- Client calls
-
Fetch Loop (repeats until termination):
- Client sends
melissa_fetch_next_parameters()request to server - Server responds with Simulation ID, Parameter values (loaded from memory-mapped array), Termination flag (indicating end of study)
- Client runs simulation with fetched parameters
- Client sends results via
melissa_send_float32()calls - Loop continues or exits based on termination flag (manual break)
- Client sends
-
Finalization Phase (once):
- Client calls
melissa_finalize()to clean up resources
Note
Actual parameter values are read by the client directly from a memory-mapped file using sim_id as the row index, eliminating the need to transmit large parameter arrays over the network.
Server-Side Simulation Assignment¶
The server maintains a queue of simulation IDs (0 to N-1) and assigns them to persistent clients on demand:
- When a persistent client requests the next parameters, the server pops a simulation ID from the queue
- The mapping
sim_id → persistent_client_idis recorded for failure detection
This allows the server to dynamically distribute simulations across available persistent clients without pre-assigning them at startup.
Example of a Persistent Client Simulation Loop¶
from mpi4py import MPI
from melissa.client.api import (
melissa_init,
melissa_finalize,
melissa_send_float32,
melissa_fetch_next_parameters,
)
def solve_system(parameters, tf: float, dt: float):
t = 0.0
state = parameters
while t < tf:
state = stepper(state, dt)
t += dt
yield state
def main():
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
vect_size = len(initial_conditions)
melissa_init("field_state", vect_size, comm)
while True:
fetched = melissa_fetch_next_parameters()
if fetched.is_terminated:
break
sim_id = fetched.sim_id
parameters = fetched.parameters
if rank == 0:
print(f"Running simulation {sim_id} with parameters {parameters}")
for timestep, state in enumerate(solve_system(parameters, tf=10.0, dt=0.01)):
melissa_send_float32("field_state", state)
melissa_finalize()
if __name__ == "__main__":
main()
Practical Guidance
-
Parallelism:
job_limitcontrols how many persistent clients run in parallel. Size it to fully utilize your allocated resources. -
Job Status:
timer_delaydoes not govern job submission in persistent client mode, but a short interval is still recommended for early failure detection. -
Scheduling: The server assigns simulations from a queue to whichever client is available next. There is no affinity between a client and its simulations. All simulations are assumed to be homogeneous in resources, MPI communicator usage, and runtimes. It is expected that any simulation should run under any persistent client.
-
Server failure: All running clients are restarted and any incomplete simulations are moved to the front of the queue, so they run before the new ones.
-
Client failure: The failed persistent client is replaced with a new one under a fresh ID, preserving the original client's error logs. Its incomplete simulations are likewise prioritized at the front of the queue.
-
Timeouts: Persistent clients are expected to run for the full study walltime, so the server does not apply timeout logic to them i.e fault-tolerance will not check for the timeouts and restart these clients.