Multiprocessing.cpu_count should not be used

Hello,

multiprocessing.cpu_count() looks to be used as a basis to determine the number of cores to be used for different processing aspect in multiple place:

$ rg multiprocessing.cpu_count 3.3.2 2>/dev/null
3.3.2/cryosparc_worker/bin/connect.py
121:    num_cpus = multiprocessing.cpu_count()

3.3.2/cryosparc_master/cryosparc_webapp/bundle/programs/server/node_modules/node-gyp/gyp/pylib/gyp/input.py
604:        parallel_state.pool = multiprocessing.Pool(multiprocessing.cpu_count())

3.3.2/cryosparc_master/cryosparc_app/api/nodejs/lib/node_modules/npm/node_modules/node-gyp/gyp/pylib/gyp/input.py
602:        parallel_state.pool = multiprocessing.Pool(multiprocessing.cpu_count())

3.3.2/cryosparc_worker/cryosparc_compute/fourier.py
19:#fft_threads = multiprocessing.cpu_count()
20:fft_threads = min(multiprocessing.cpu_count(), 4)

3.3.2/cryosparc_worker/cryosparc_compute/sigproc.py
922:            pool = Pool(multiprocessing.cpu_count())

3.3.2/cryosparc_worker/cryosparc_compute/jobs/topaz/build_topaz.py
151:        elif cpu_count < 0: cpu_count = multiprocessing.cpu_count()
379:        elif cpu_count < 0: cpu_count = multiprocessing.cpu_count()
466:        elif cpu_count < 0: cpu_count = multiprocessing.cpu_count()

3.3.2/cryosparc_worker/cryosparc_compute/jobs/topaz/run_topaz_denoise.py
241:            num_cpu = multiprocessing.cpu_count()

3.3.2/cryosparc_worker/cryosparc_compute/jobs/topaz/run_topaz.py
181:            num_cpu = multiprocessing.cpu_count()
588:        num_cpu = multiprocessing.cpu_count()
1032:            num_cpu = multiprocessing.cpu_count()

3.3.2/cryosparc_worker/cryosparc_compute/newfourier.py
19:fft_threads = max(multiprocessing.cpu_count(), 8)

3.3.2/cryosparc_master/cryosparc_compute/jobs/topaz/run_topaz_denoise.py
241:            num_cpu = multiprocessing.cpu_count()

3.3.2/cryosparc_master/cryosparc_compute/jobs/topaz/run_topaz.py
181:            num_cpu = multiprocessing.cpu_count()
588:        num_cpu = multiprocessing.cpu_count()
1032:            num_cpu = multiprocessing.cpu_count()

3.3.2/cryosparc_master/cryosparc_compute/jobs/topaz/build_topaz.py
151:        elif cpu_count < 0: cpu_count = multiprocessing.cpu_count()
379:        elif cpu_count < 0: cpu_count = multiprocessing.cpu_count()
466:        elif cpu_count < 0: cpu_count = multiprocessing.cpu_count()

3.3.2/cryosparc_master/cryosparc_compute/fourier.py
19:#fft_threads = multiprocessing.cpu_count()
20:fft_threads = min(multiprocessing.cpu_count(), 4)

3.3.2/cryosparc_master/cryosparc_compute/newfourier.py
19:fft_threads = max(multiprocessing.cpu_count(), 8)

3.3.2/cryosparc_master/cryosparc_app/api/bundle/programs/server/node_modules/node-gyp/gyp/pylib/gyp/input.py
602:        parallel_state.pool = multiprocessing.Pool(multiprocessing.cpu_count())

3.3.2/cryosparc_master/cryosparc_compute/sigproc.py
922:            pool = Pool(multiprocessing.cpu_count())

3.3.2/cryosparc_master/cryosparc_webapp/nodejs/lib/node_modules/npm/node_modules/node-gyp/gyp/pylib/gyp/input.py
604:        parallel_state.pool = multiprocessing.Pool(multiprocessing.cpu_count())

3.3.2/cryosparc_master/cryosparc_liveapp/nodejs/lib/node_modules/npm/node_modules/node-gyp/gyp/pylib/gyp/input.py
609:        parallel_state.pool = multiprocessing.Pool(multiprocessing.cpu_count())

3.3.2/cryosparc_master/cryosparc_liveapp/bundle/programs/server/node_modules/node-gyp/gyp/pylib/gyp/input.py
609:        parallel_state.pool = multiprocessing.Pool(multiprocessing.cpu_count())

The problem is that this function returns the number of cpu in the machine and this is not the same as the number of cpu available to the process. For example, if you run cryosparc using taskset or a batch scheduler like slurm:

$ taskset -c 1 nproc
1
$ taskset -c 1 python3 -c "import multiprocessing; print(multiprocessing.cpu_count())"
96

If I run cryosparc in a single core allocation, much more threads could be be spawned and fight for a single core. A solution would be to use os.sched_getaffinity instead of multiprocessing.cpu_count on platform supporting it:

$ python3 -c "import os; print(len(os.sched_getaffinity(0)))"
96
$ taskset -c 1 python3 -c "import os; print(len(os.sched_getaffinity(0)))"
1

What do you think ?