| 134 | |
| 135 | |
| 136 | class MpiPoolSession(MpiSession): |
| 137 | |
| 138 | def __init__(self, n_workers: int): |
| 139 | self.n_workers = n_workers |
| 140 | self.mpi_pool: Optional[MPIPoolExecutor] = None |
| 141 | self._start_mpi_pool() |
| 142 | if ENABLE_MULTI_DEVICE: |
| 143 | self.comm = mpi4py.MPI.COMM_WORLD |
| 144 | |
| 145 | def get_comm(self): |
| 146 | return self.comm |
| 147 | |
| 148 | def submit(self, task: Callable[..., T], *args, |
| 149 | **kwargs) -> List[Future[T]]: |
| 150 | return [ |
| 151 | self.mpi_pool.submit(task, *args, **kwargs) |
| 152 | for i in range(self.n_workers) |
| 153 | ] |
| 154 | |
| 155 | def submit_sync(self, task: Callable[..., T], *args, **kwargs) -> List[T]: |
| 156 | futures = [ |
| 157 | self.mpi_pool.submit(task, *args, **kwargs) |
| 158 | for i in range(self.n_workers) |
| 159 | ] |
| 160 | return [future.result() for future in futures] |
| 161 | |
| 162 | def shutdown(self, wait=True): |
| 163 | if self.mpi_pool is not None: |
| 164 | self.mpi_pool.shutdown(wait=wait) |
| 165 | self.mpi_pool = None |
| 166 | |
| 167 | def abort(self): |
| 168 | self.get_comm().Abort(1) |
| 169 | |
| 170 | def _start_mpi_pool(self): |
| 171 | assert not self.mpi_pool, 'MPI session already started' |
| 172 | |
| 173 | self.mpi_pool = MPIPoolExecutor(max_workers=self.n_workers, |
| 174 | path=sys.path) |
| 175 | |
| 176 | def __del__(self): |
| 177 | self.shutdown_abort() |
| 178 | |
| 179 | def __reduce__(self): |
| 180 | raise TypeError('cannot pickle MPI session') |
| 181 | |
| 182 | |
| 183 | class MpiCommSession(MpiSession): |
no outgoing calls