cosmo parallel get nproc available skl

function nproc_available = cosmo_parallel_get_nproc_available(varargin)
    % get number of processes available from Matlab parallel processing pool
    %
    % nproc=cosmo_parallel_get_nproc_available()
    %
    % Input:
    %   'nproc',nproc_wanted            Number of desired processes (optional)
    %                                   If not provided, then the number of
    %                                   available cores is returned.
    %                                   Use 'nproc',inf to get as many
    %                                   cores as there available.
    %   'nproc_available_query_func',f  Function handle to determine how many
    %                                   processes are available. This function
    %                                   is intended for use by developers only;
    %                                   by default it selects the appropriate
    %                                   function based on the platform (Octave,
    %                                   Matlab <= 2013b, or Matlab > 2013b)
    %
    % Output:
    %   nproc_available                 Number of available parallel processes.
    %                                   - On Matlab: this requires the parallel
    %                                     computing toolbox
    %                                   - On Octave: this requires the parallel
    %                                     toolbox
    %                                   If the required toolbox is not
    %                                   available, then nproc_available=1.
    %                                   If there are nproc_available
    %                                   processes available and
    %                                       nproc_available<nproc_wanted
    %                                   then nproc=nproc_available is returned.
    %
    % Notes:
    %   - If no parallel processing pool has been started, then this function
    %     will try to start one (with as many parallel processes as possible)
    %     before counting the number of processes available.
    %   - If a parallel processing pool has already been started, then this
    %     function returns the number of processes available it that pool. This
    %     function *does not* close an existing pool and open a new one. This
    %     means that if a user has started a pool with M processes on a machine
    %     with N processes available (i.e. a pool has started with fewer
    %     processes than available), then this function will return M (and not
    %     N if M<N). If you need a fresh pool with
    %
    % See also: parcellfun, matlabpool
    %
    % #   For CoSMoMVPA's copyright information and license terms,   #
    % #   see the COPYING file distributed with CoSMoMVPA.           #

    defaults = struct();
    opt = cosmo_structjoin(defaults, varargin{:});
    check_inputs(opt);

    [has_nproc_wanted, nproc_wanted] = get_nproc_wanted(opt);
    if has_nproc_wanted && nproc_wanted <= 1
        nproc_available = 1;
        return
    end

    max_nproc_available_query_func = get_max_nproc_available_func(opt);
    [max_nproc_available, msg] = max_nproc_available_query_func();

    if ~has_nproc_wanted
        nproc_available = max_nproc_available;
        return
    end

    % getting here it means opt.nproc>1, i.e. the user asked for more than
    %
    nproc_wanted = opt.nproc;
    nproc_available = max_nproc_available;

    if nproc_wanted > max_nproc_available
        full_msg = sprintf(['''nproc''=%d requested, but %s. '...
                            'Using ''nproc''=%d'], ...
                           nproc_wanted, msg, nproc_available);

        if ~isinf(nproc_wanted)
            % do not show warning if nproc_wanted is infinity
            cosmo_warning(full_msg);
        end
    end

    if nproc_wanted < nproc_available
        nproc_available = nproc_wanted;
    end

function [has_nproc_wanted, nproc_wanted] = get_nproc_wanted(opt)
    nproc_wanted = NaN;

    has_nproc_wanted = isfield(opt, 'nproc');
    if has_nproc_wanted
        nproc_wanted = opt.nproc;
    end

function func = get_max_nproc_available_func(opt)
    override_key = 'nproc_available_query_func';
    if isfield(opt, override_key)
        func = opt.(override_key);
        return
    end

    if cosmo_wtf('is_matlab')
        v_num = cosmo_wtf('version_number');
        % Matlab 2013b is version 8.2
        if v_num(1) > 8
            is_matlab_ge_2013b = 1;
        else
            is_matlab_ge_2013b = v_num(1) == 8 && v_num(2) >= 2;
        end

        if is_matlab_ge_2013b
            func = @matlab_get_max_nproc_available_ge2013b;
        else
            func = @matlab_get_max_nproc_available_lt2013b;
        end
    elseif cosmo_wtf('is_octave')
        func = @octave_get_max_nproc_available;
    else
        assert(false, 'this should not happen');
    end

function check_inputs(opt)
    if isfield(opt, 'nproc')
        nproc = opt.nproc;
        if ~(isnumeric(nproc) && ...
             isscalar(nproc) && ...
             nproc >= 1 && ...
             round(nproc) == nproc)
            error('nproc must be a positive scalar');
        end
    end

function [nproc_available, msg] = matlab_get_max_nproc_available_lt2013b()
    nproc_available = 1;
    msg = check_java_and_funcs({'matlabpool'});

    if ~isempty(msg)
        return
    end

    pool_func = @matlabpool;
    open_pool_func = pool_func;
    query_pool_func = @()pool_func('size');

    % get number of processes
    try
        nproc_available = query_pool_func();
        pool_is_open = nproc_available > 0;

        if ~pool_is_open
            % try to open pool
            open_pool_func();
            nproc_available = query_pool_func();
        end
    catch
        msg = lasterr();
        return
    end

    % ensure nproc_available>=1
    nproc_available = max(nproc_available, 1);

function [nproc_available, msg] = matlab_get_max_nproc_available_ge2013b()
    msg = '';
    nproc_available = 1;

    matlab_parallel_functions = {'gcp', 'parpool'};
    if ~(usejava('jvm') && ...
         platform_has_functions(matlab_parallel_functions))
        msg = 'java or parallel functions not available';
        return
    end

    try
        pool = gcp();
        if isempty(pool)
            msg = ['Parallel toolbox is available, but '...
                   'unable to open pool'];
            return
        end
    catch
        msg = lasterr();
        return
    end
    nproc_available = pool.NumWorkers();

function msg = check_java_and_funcs(function_names)
    msg = '';
    if ~(usejava('jvm') && ...
         platform_has_functions(function_names))
        msg = 'java or parallel functions not available';
        return
    end

function [nproc_available, msg] = octave_get_max_nproc_available
    msg = '';
    nproc_available = 1;

    if ~cosmo_check_external('octave_pkg_parallel', false)
        msg = 'parallel toolbox is not available';
        return
    end

    nproc_available = nproc('overridable');

function tf = platform_has_functions(function_names)
    tf = all(cellfun(@(x)~isempty(which(x)), function_names));