Skip to content

Commit 3f3a119

Browse files
committed
Use fork (Gemini idea) to stop losing locks in /dev/shm
1 parent d9d9da3 commit 3f3a119

1 file changed

Lines changed: 32 additions & 14 deletions

File tree

ImageD11/sinograms/lima_segmenter.py

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@
88
- read an input file which has the source/destination file names for this job
99
"""
1010

11+
import os
12+
# because multiprocessing
13+
os.environ["HDF5_USE_FILE_LOCKING"] = "FALSE"
1114

1215
import sys
1316
import time
14-
import os
1517
import math
1618
import logging
1719
import numpy as np
@@ -368,25 +370,40 @@ def main(h5name, jobid):
368370
)
369371
)
370372
if options.cores_per_job > 1:
371-
ImageD11.cImageD11.check_multiprocessing(patch=True) # avoid fork
372373
import multiprocessing
373-
374-
with multiprocessing.Pool(
375-
processes=options.cores_per_job,
374+
# Gemini suggested fork to suppress the multiprocessing context errors
375+
# We must ensure that hdf5 has not got any files open when doing this
376+
# Both spawn and forkserver run into problems reproducibly.
377+
ctx = multiprocessing.get_context('fork')
378+
num_processes = min(options.cores_per_job, len(args))
379+
print("# Starting pool with", num_processes, " workers...", flush=True)
380+
381+
mypool = ctx.Pool(
382+
processes=num_processes,
376383
initializer=initOptions,
377384
initargs=(h5name, jobid),
378-
) as mypool:
385+
)
386+
try:
379387
donefile = sys.stdout
380-
for fname in mypool.map(segment_lima, args, chunksize=1):
381-
donefile.write(fname + "\n")
388+
for fname in mypool.imap_unordered(segment_lima, args, chunksize=1):
389+
donefile.write(str(fname) + "\n")
382390
donefile.flush()
391+
except Exception as e:
392+
print(f"Main loop error: {e}", file=sys.stderr)
393+
# If the main loop dies, we must kill the pool to stop things hanging
394+
mypool.terminate()
395+
finally:
396+
# 4. Clean shutdown
397+
print("# Closing pool...", flush=True)
398+
mypool.close()
399+
mypool.join()
400+
print("# Pool closed.", flush=True)
383401
else:
384402
for arg in args:
385403
fname = segment_lima(arg)
386404
print(fname)
387405
sys.stdout.flush()
388-
389-
print("All done")
406+
print("# All done")
390407

391408

392409
def setup_slurm_array(dsname, dsgroup="/", pythonpath=None):
@@ -434,7 +451,7 @@ def setup_slurm_array(dsname, dsgroup="/", pythonpath=None):
434451
#SBATCH --job-name=array-lima_segmenter
435452
#SBATCH --output=%s/lima_segmenter_%%A_%%a.out
436453
#SBATCH --error=%s/lima_segmenter_%%A_%%a.err
437-
#SBATCH --array=0-%d
454+
#SBATCH --array=1-%d
438455
#SBATCH --time=02:00:00
439456
# define memory needs and number of tasks for each array job
440457
#SBATCH --ntasks=1
@@ -443,10 +460,11 @@ def setup_slurm_array(dsname, dsgroup="/", pythonpath=None):
443460
date
444461
echo Running on $HOSTNAME : %s
445462
# Hypothesis: multiprocessing collisions in /tmp
446-
mkdir /tmp/$USER_$SLURM_ARRAY_TASK_ID
447-
export TMPDIR=/tmp/$USER_$SLURM_ARRAY_TASK_ID
463+
export TMPDIR="/tmp/${USER}_${SLURM_JOB_ID}_${SLURM_ARRAY_TASK_ID}"
464+
echo $TMPDIR
465+
mkdir $TMPDIR
448466
OMP_NUM_THREADS=1 %s > %s/lima_segmenter_$SLURM_ARRAY_TASK_ID.log 2>&1
449-
rm -rf /tmp/$USER_$SLURM_ARRAY_TASK_ID/
467+
rm -rf $TMPDIR
450468
date
451469
"""
452470
% (sdir, sdir, jobs_needed, options.cores_per_job, command, command, sdir)

0 commit comments

Comments
 (0)