'Solves a DCP compliant optimization problem in parallel.
Saves the values of primal and dual variables in the variable
and constraint objects, respectively.
Parameters
solver : str, optional
The solver to use. Defaults to ECOS.
ignore_dcp : bool, optional
Overrides the default of raising an exception if the problem is not
DCP.
warm_start : bool, optional
Should the previous solver result be used to warm start?
verbose : bool, optional
Overrides the default of hiding solver output.
kwargs : dict, optional
A dict of options that will be passed to the specific solver.
In general, these options will override any default settings
imposed by cvxpy.
Returns
float
The optimal value for the problem, or a string indicating
why the problem could not be solved.'

def _parallel_solve(self, solver=None, ignore_dcp=False, warm_start=False, verbose=False, **kwargs):

    def _solve_problem(problem):
        'Solve    a    problem    and    then    return    the    optimal    value,    status,\n                                                primal    values,    and    dual    values.\n                                                '
        opt_value = problem.solve(solver=solver, ignore_dcp=ignore_dcp, warm_start=warm_start, verbose=verbose, parallel=False, **kwargs)
        status = problem.status
        primal_values = [var.value for var in problem.variables()]
        dual_values = [constr.dual_value for constr in problem.constraints]
        return SolveResult(opt_value, status, primal_values, dual_values)
    pool = multiprocessing.Pool(processes=multiprocessing.cpu_count())
    solve_results = pool.map(_solve_problem, self._separable_problems)
    pool.close()
    pool.join()
    statuses = {solve_result.status for solve_result in solve_results}
    for status in s.INF_OR_UNB:
        if (status in statuses):
            self._handle_no_solution(status)
            break
    else:
        for (subproblem, solve_result) in zip(self._separable_problems, solve_results):
            for (var, primal_value) in zip(subproblem.variables(), solve_result.primal_values):
                var.save_value(primal_value)
            for (constr, dual_value) in zip(subproblem.constraints, solve_result.dual_values):
                constr.save_value(dual_value)
        self._value = sum((solve_result.opt_value for solve_result in solve_results))
        if (s.OPTIMAL_INACCURATE in statuses):
            self._status = s.OPTIMAL_INACCURATE
        else:
            self._status = s.OPTIMAL
    return self._value
