def _test_mpi_partition(comm): test_ranks = [0] if comm is not None: import mpi4py.MPI test_ranks = list(range(comm.size)) for x in ( [], ["a"], ["a", "b"], ["a", "b", "c"], ["a", "b", "c"] * 2, ["a", "b", "c"] * 4, ["a", "b", "c"] * 16, ["a", "b", "c"] * 32, ): for root in test_ranks: x_accessed_local = array.array("i", [0]) * len(x) for i, xi in mpi_partition(comm, list(enumerate(x)), root=root): assert x[i] == xi x_accessed_local[i] += 1 x_accessed = array.array("i", [0]) * len(x) if comm is not None: comm.Allreduce( [x_accessed_local, mpi4py.MPI.INT], [x_accessed, mpi4py.MPI.INT], op=mpi4py.MPI.SUM, ) comm.Barrier() else: x_accessed[:] = x_accessed_local[:] for xi in x_accessed: assert xi == 1
def _tighten_bounds_impl(self, tmp_objective): objlist = self.range_reduction_get_objects() joblist = [] objects = [] lower_bounds = [] upper_bounds = [] objects_seen = set() for i, val in enumerate(objlist): obj = None include = False val = val if type(val) is tuple else (val, True, True) assert len(val) == 3 obj = val[0] cid = self.problem.pyomo_object_to_cid[obj] if val[1]: include = True joblist.append((i, cid, 'L')) if val[2]: include = True joblist.append((i, cid, 'U')) joblist.append((i, cid, 'U')) if include: assert obj is not None assert id(obj) not in objects_seen objects_seen.add(id(obj)) objects.append(obj) lower_bounds.append(pmo.value(obj.lb) \ if obj.has_lb() else \ -inf) upper_bounds.append(pmo.value(obj.ub) \ if obj.has_ub() else \ inf) lower_bounds = array.array('d', lower_bounds) upper_bounds = array.array('d', upper_bounds) # verify that everyone has the exact same list # (order and values), assumes everything in the list # has a well-defined hash if self._comm is not None: my_joblist_hash = hash_joblist(joblist) joblist_hash = self._comm.bcast(my_joblist_hash, root=0) assert joblist_hash == my_joblist_hash for i, cid, which in mpi_partition(self._comm, joblist): obj = self.problem.cid_to_pyomo_object[cid] tmp_objective.expr = obj if which == 'L': tmp_objective.sense = pmo.minimize else: assert which == 'U' tmp_objective.sense = pmo.maximize self.range_reduction_objective_changed(tmp_objective) bound = self.range_reduction_solve_for_object_bound(obj) if bound is not None: if which == 'L': lower_bounds[i] = bound else: assert which == 'U' upper_bounds[i] = bound if self._comm is not None: lower_bounds_local = lower_bounds upper_bounds_local = upper_bounds lower_bounds = array.array('d', lower_bounds) upper_bounds = array.array('d', upper_bounds) self._comm.Allreduce([lower_bounds_local, mpi4py.MPI.DOUBLE], [lower_bounds, mpi4py.MPI.DOUBLE], op=mpi4py.MPI.MAX) self._comm.Allreduce([upper_bounds_local, mpi4py.MPI.DOUBLE], [upper_bounds, mpi4py.MPI.DOUBLE], op=mpi4py.MPI.MIN) return objects, lower_bounds, upper_bounds