Speed up simulations by distributing replicates across Josh Cloud
Introduction
Josh Cloud is free community infrastructure for running Josh simulations at scale. When you have sweeps with many replicates, Josh Cloud runs them in parallel - significantly faster than sequential local execution.
How It Works
Your local machine runs Josh as a coordinator
Replicates are distributed across Josh Cloud workers
Results are collected and returned to your local machine
The computation happens in the cloud - very resource-light locally
Getting an API Key
Josh Cloud is a free service provided by the Eric and Wendy Schmidt Center for Data Science and Environment. To request access:
Store your API key in a .env file in your project root:
# .env
JOSH_API_KEY=your-api-key-here
from dotenv import load_dotenvimport osimport timefrom pathlib import Pathfrom joshpy.cli import JoshCLIfrom joshpy.jar import JarModefrom joshpy.jobs import JobConfig, SweepConfig, ConfigSweepParameterfrom joshpy.strategies import CartesianStrategyfrom joshpy.sweep import SweepManager# Load API key from .env fileload_dotenv()api_key = os.environ["JOSH_API_KEY"] # Fails fast if not setdev_endpoint = os.environ.get("JOSH_DEV_ENDPOINT")print(f"API key loaded: {api_key[:8]}...")# Shared CLI instancecli = JoshCLI(josh_jar=JarMode.DEV)# Use maxGrowth=42 - a unique value not used by other tutorials# This ensures output files don't collide with other tutorial runsPARAM_VALUE =42
API key loaded: dYt1oSfr...
Local vs Cloud: Speed Comparison
Let’s compare execution time for a sweep with 100 replicates.
Local Execution (Sequential)
Running locally, all 100 replicates execute one after another:
# Clean up any stale files from this tutorialfor f in Path("/tmp").glob(f"tutorial_sweep_{PARAM_VALUE}_*.csv"): f.unlink()config = JobConfig( template_path=Path("../../examples/templates/sweep_config.jshc.j2"), source_path=Path("../../examples/tutorial_sweep.josh"), simulation="Main", replicates=100, sweep=SweepConfig( config_parameters=[ ConfigSweepParameter(name="maxGrowth", values=[PARAM_VALUE]), ], strategy=CartesianStrategy(), ),)manager_local = ( SweepManager.builder(config) .with_registry(":memory:", experiment_name="local_benchmark") .with_cli(cli) .build())print(f"Running {config.replicates} replicates locally...")start_time = time.time()results_local = manager_local.run()local_duration = time.time() - start_timeprint(f"\nLocal execution: {local_duration:.1f} seconds")print(f"Succeeded: {results_local.succeeded}, Failed: {results_local.failed}")manager_local.cleanup()manager_local.close()
Always load from environment variables or .env files:
from dotenv import load_dotenvimport osload_dotenv()api_key = os.environ["JOSH_API_KEY"]results = manager.run(remote=True, api_key=api_key)
Test Locally First
Before running large cloud sweeps, verify your simulation works locally:
# First: small local testresults = manager.run() # local executionassert results.failed ==0, "Fix issues before scaling to cloud"# Then: scale up with cloud executionresults = manager.run(remote=True, api_key=api_key)