diff --git a/CHANGELOG.md b/CHANGELOG.md index 9cc7b77d1d56df4e7e45b2fd135e535c69d650d0..71a0dae4e4821d03c0aec37a3b87f03fd39e5683 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ - Some labels and the title for the SED plots has been improved to avoid overlaps and overflows. (Médéric Boquien) - Ensure that best models are properly computed when models are computed by blocks and that no fit could be made in one or more blocks. This can be case if all the models in the block are older than the age of the universe. (Médéric) - Make sure that the parameters are saved with the proper scale (linear or logarithmic) in the χ² files. (Médéric Boquien) +- Some math libraries such as MKL or OpenBLAS sometime try to be (too) smart, starting computation threads on their own. As cigale is already parallel, this just oversubscribes the CPU and can lead to important slowdowns. An environment variable could be set to disable this, but this is cumbersome. Disabling within the code did not seem to work. A different method has been implement, which should address the issue to forcefully disable threading in these libraries. (Médéric Boquien) ### Optimised - Slight speedup of the computation of the likelihood from the χ² using a multiplication rather than a division. (Médéric Boquien) - Speedup of the computation of the χ² by ~10% taking the opposite of a scalar rather than of an array. (Médéric Boquien) diff --git a/pcigale/analysis_modules/pdf_analysis/workers.py b/pcigale/analysis_modules/pdf_analysis/workers.py index 434b8ac4f699898ba79ffe50c6b7f05fb8176afb..02d23847966bbd8673b4890f09435523524e787b 100644 --- a/pcigale/analysis_modules/pdf_analysis/workers.py +++ b/pcigale/analysis_modules/pdf_analysis/workers.py @@ -10,8 +10,8 @@ from copy import deepcopy import numpy as np -from ..utils import nothread from .utils import save_chi2, compute_corr_dz, compute_chi2, weighted_param +from ..utils import nothreading from ...warehouse import SedWarehouse @@ -30,7 +30,7 @@ def init_sed(models, counter): # Limit the number of threads to 1 if we use MKL in order to limit the # oversubscription of the CPU/RAM. - nothread() + nothreading() gbl_warehouse = SedWarehouse() @@ -53,6 +53,9 @@ def init_analysis(models, results, counter): """ global gbl_models, gbl_obs, gbl_results, gbl_counter + # Limit the number of threads to 1 to limit the oversubscription of the CPU + nothreading() + gbl_models = models gbl_obs = models.obs gbl_results = results @@ -79,6 +82,9 @@ def init_bestfit(conf, params, observations, results, counter): global gbl_warehouse, gbl_conf, gbl_params, gbl_obs global gbl_results, gbl_counter + # Limit the number of threads to 1 to limit the oversubscription of the CPU + nothreading() + gbl_warehouse = SedWarehouse() gbl_conf = conf diff --git a/pcigale/analysis_modules/savefluxes/workers.py b/pcigale/analysis_modules/savefluxes/workers.py index 3639297c6e742d6da5c71bdabd200dd60476bbfe..9362f4378a4c21c8f2ade81f5cf0a56680d38cdf 100644 --- a/pcigale/analysis_modules/savefluxes/workers.py +++ b/pcigale/analysis_modules/savefluxes/workers.py @@ -7,8 +7,8 @@ import numpy as np +from ..utils import nothreading from ...warehouse import SedWarehouse -from ..utils import nothread def init_fluxes(models, counter): @@ -26,9 +26,8 @@ def init_fluxes(models, counter): """ global gbl_warehouse, gbl_models, gbl_obs, gbl_save, gbl_counter - # Limit the number of threads to 1 if we use MKL in order to limit the - # oversubscription of the CPU/RAM. - nothread() + # Limit the number of threads to 1 to limit the oversubscription of the CPU + nothreading() gbl_warehouse = SedWarehouse() diff --git a/pcigale/analysis_modules/utils.py b/pcigale/analysis_modules/utils.py index 3727afdb0761d22f207da569e1db7b0dd4be592a..8f0c290cc6804a5610144791e643bcee10742b79 100644 --- a/pcigale/analysis_modules/utils.py +++ b/pcigale/analysis_modules/utils.py @@ -6,11 +6,13 @@ """ Various utility functions for pcigale analysis modules """ +import ctypes +from ctypes.util import find_library import multiprocessing as mp import time -def nothread(): +def nothreading(): """Some libraries such as Intel's MKL have automatic threading. This is good when having only one process. However we already do our own parallelisation. The additional threads created by the MKL increase in @@ -25,12 +27,21 @@ def nothread(): None """ - try: - import mkl - mkl.set_num_threads(1) - except ImportError: + try: # Disable threading for MKL + name = find_library('mkl_rt') + if name: + lib = ctypes.cdll.LoadLibrary(name) + lib.mkl_set_num_threads(ctypes.byref(ctypes.c_int(1))) + except: pass + try: # Disable threading for OpenBLAS + name = find_library('openblas') + if name: + lib = ctypes.cdll.LoadLibrary(name) + lib.openblas_set_num_threads(ctypes.c_int(1)) + except: + pass class Counter: """Class to count the number of models computers/objects analysed. It has