The sotrp command has two runners. The runner field of the config selects
the runner:
runner |
Class | Code | How it runs the maps |
|---|---|---|---|
basic (default) |
PipelineRunner |
sotrplib/handlers/basic.py |
One map after the other, in one process. |
prefect |
PrefectRunner |
sotrplib/handlers/prefect.py |
Each map in a separate worker process, in parallel. |
The two runners do the same steps. The steps are in BaseRunner
(sotrplib/handlers/base.py). The prefect runner also shows each step on the
prefect dashboard.
Use the prefect runner to analyze many maps in one job, for example all the depth-1 maps of one day. The runner needs all the maps of a run at the same time for map matching.
BaseRunner.run() is a prefect flow. The flow does these steps:
- The map coadder groups the maps (
group_maps()). With the default coadder, each map is one group. - The flow sends each group to a worker process (
ProcessPoolTaskRunner). The worker builds the map, applies the preprocessors and does the photometry, the blind search and the sifter. The worker writes the map outputs (FITS files). - The worker returns a
MapResult(sotrplib/sifter/map_matching.py) to the main process. AMapResultcontains the candidates and the map data that the next steps need. It does not contain the map, so it is small. - When all the workers are complete, the map matcher groups the transient candidates across the maps. See Map matching.
- The main process writes the source outputs of each map. Then it sets the
processing status of each map to
completed.
The main process keeps the MapResult of each map in memory until step 5.
Thus, the source outputs of a map contain the results of the map matching.
-
Install the
prefectextra:uv sync --extra prefect -
Each object that the config makes must be serializable with
cloudpickle. The runner sends the objects to the worker processes. For example,SOCatremoves its database client before serialization and connects again in the worker. The worker gets thesocat_*environment variables from the main process. -
The workers use the working directory of the command. Put the files that the library reads from the working directory in that directory. For example, the planet mask reads
de440s.bspfrom the working directory. If the file is not there, skyfield tries to download it.
See "Run with prefect" in the README. If you
do not start a prefect server, sotrp starts a temporary server.
Start a prefect server in each job. A compute node has no network access, and a server of a different job can use the same port.
Write a file, for example env_prefect, that you source in the job:
#!/bin/bash
# Database and catalog settings for the run.
export MAPCAT_DEPTH_ONE_PARENT='/path/to/depth1/'
export MAPCAT_DATABASE_NAME='/path/to/mapcat.sqlite'
export socat_client_client_type=db
export socat_model_database_name='/path/to/socat.db'
export TELEMETRY__ENABLE=false
export sotrp_runner=prefect
# Keep the prefect files on the node, one directory for each job.
export TMPDIR=${TMPDIR:-/tmp}/$USER/prefect_${SLURM_JOB_ID:-local}
mkdir -p $TMPDIR
export PREFECT_HOME=$TMPDIR/prefect
mkdir -p $PREFECT_HOME
# Use a different port for each job, so that jobs on one node do not share a server.
PORT=$((6000 + ${SLURM_JOB_ID:-969} % 2000))
export PREFECT_API_URL=http://127.0.0.1:$PORT/api
export PREFECT_SERVER_API_HOST=127.0.0.1
export PREFECT_SERVER_API_PORT=$PORT
# The process pool uses all the cores of the node by default, not the cores of the job.
export PREFECT_TASKS_RUNNER_PROCESS_POOL_MAX_WORKERS=${SLURM_CPUS_PER_TASK:-4}
# Start the server without a terminal. Then wait until it is ready.
prefect server start --host 127.0.0.1 --port $PORT < /dev/null > $PREFECT_HOME/server.log 2>&1 &
PREFECT_SERVER_PID=$!
until curl -s $PREFECT_API_URL/health > /dev/null; do sleep 1; doneSet PREFECT_TASKS_RUNNER_PROCESS_POOL_MAX_WORKERS. If you do not set
it, the process pool starts one worker for each core of the node. Each worker
keeps one map in memory, so the job can use more memory than it has.
#!/bin/bash
#SBATCH --job-name=sotrp_prefect_day
#SBATCH --nodes=1
#SBATCH --ntasks=1
#SBATCH --cpus-per-task=8
#SBATCH --mem=128G
#SBATCH --time=02:00:00
# The working directory must contain de440s.bsp (see "Requirements").
cd /path/to/sotrplib
source .venv/bin/activate
source /path/to/env_prefect
sotrp -c /path/to/config.json
STATUS=$?
kill $PREFECT_SERVER_PID
exit $STATUSEach worker keeps one depth-1 map and its filtered maps in memory. For the lat-iso depth-1 maps (0.5 GB to 0.8 GB of FITS files for each map), these jobs completed:
| Maps | Bands | Workers | Time | Peak memory |
|---|---|---|---|---|
| 8 | 1 | 4 | 5 min | 16 GB |
| 4 | 1 | 4 | 3 min | 14 GB |
| 24 | 4 | 8 | 9 min | 29 GB |
Use approximately 4 GB for each worker, plus the memory of the main process.
Map matching compares only the maps of one run. To match detections across the bands, put all the bands in one run:
-
In
maps, do not setfrequencyorarray. Setstart_timeandend_timeto the day. -
In the
matched_filterpreprocessor, give one beam profile for each band:{ "preprocessor_type": "matched_filter", "beam1d": { "f090": "/path/to/profile_f090.txt", "f150": "/path/to/profile_f150.txt", "f220": "/path/to/profile_f220.txt", "f280": "/path/to/profile_f280.txt" } }The preprocessor selects the profile with the
frequencyof each map. If a band has no profile, the preprocessor raisesValueError. -
Add a
map_matcher(see Map matching). -
Set
"runner": "prefect".
With a mapcat reader, the runner writes the status of each map in the
time_domain_processing table of mapcat:
- The reader sets
processingwhen it reads the map. - The main process sets
completedafter it writes the source outputs of the map. - If the analysis or the source outputs of a map raise an exception, the
runner sets
failed.
The reader does not read a map with the status completed. To analyze the
maps again, set "rerun": true in maps.
| Error | Cause | Solution |
|---|---|---|
TypeError: cannot pickle 'weakref.ReferenceType' object |
An object of the runner is not serializable, for example a database client. | Remove the object before serialization, as SOCat does (__getstate__ and __setstate__). |
cannot download https://ssd.jpl.nasa.gov/.../de440s.bsp |
The file is not in the working directory, and the node has no network access. | Put de440s.bsp in the working directory of the job. |
| The job uses too much memory, or SLURM stops it. | There are too many workers. | Set PREFECT_TASKS_RUNNER_PROCESS_POOL_MAX_WORKERS. |
| The server does not start, or the flow uses the server of a different job. | Two jobs on one node use the same port. | Calculate the port from SLURM_JOB_ID. |