|
1 | 1 | # -*- coding: utf-8 -*- |
2 | 2 | import asyncio |
| 3 | +import concurrent.futures as concurrent |
3 | 4 | import functools |
4 | 5 | import inspect |
5 | | -import concurrent.futures as concurrent |
6 | | -import warnings |
| 6 | +import os |
7 | 7 | import time |
| 8 | +import warnings |
8 | 9 |
|
9 | 10 | from .notebook_integration import live_plot, live_info, in_ipynb |
10 | 11 |
|
|
27 | 28 | pass |
28 | 29 |
|
29 | 30 |
|
| 31 | +if os.name == 'nt': |
| 32 | + if with_distributed: |
| 33 | + _default_executor = distributed.Client |
| 34 | + _default_executor_kwargs = {'address': distributed.LocalCluster()} |
| 35 | + else: |
| 36 | + _windows_executor_msg = ( |
| 37 | + "The default executor on Windows for 'adaptive.Runner' cannot " |
| 38 | + "be used because the package 'distributed' is not installed. " |
| 39 | + "Either install 'distributed' or explicitly specify an executor " |
| 40 | + "when using 'adaptive.Runner'." |
| 41 | + ) |
| 42 | + |
| 43 | + _default_executor_kwargs = {} |
| 44 | + |
| 45 | + def _default_executor(*args, **kwargs): |
| 46 | + raise RuntimeError(_windows_executor_msg) |
| 47 | + |
| 48 | + warnings.warn(_windows_executor_msg) |
| 49 | + |
| 50 | +else: |
| 51 | + _default_executor = concurrent.ProcessPoolExecutor |
| 52 | + _default_executor_kwargs = {} |
| 53 | + |
| 54 | + |
| 55 | + |
30 | 56 | class BaseRunner: |
31 | 57 | """Base class for runners that use concurrent.futures.Executors. |
32 | 58 |
|
@@ -86,9 +112,12 @@ class BlockingRunner(BaseRunner): |
86 | 112 | The end condition for the calculation. This function must take |
87 | 113 | the learner as its sole argument, and return True when we should |
88 | 114 | stop requesting more points. |
89 | | - executor : concurrent.futures.Executor, or ipyparallel.Client, optional |
| 115 | + executor : concurrent.futures.Executor, distributed.Client, |
| 116 | + or ipyparallel.Client, optional |
90 | 117 | The executor in which to evaluate the function to be learned. |
91 | | - If not provided, a new ProcessPoolExecutor is used. |
| 118 | + If not provided, a new `ProcessPoolExecutor` is used on Unix systems |
| 119 | + while on Windows a `distributed.Client` is used if `distributed` is |
| 120 | + installed. |
92 | 121 | ntasks : int, optional |
93 | 122 | The number of concurrent function evaluations. Defaults to the number |
94 | 123 | of cores available in 'executor'. |
@@ -183,9 +212,12 @@ class AsyncRunner(BaseRunner): |
183 | 212 | the learner as its sole argument, and return True when we should |
184 | 213 | stop requesting more points. If not provided, the runner will run |
185 | 214 | forever, or until 'self.task.cancel()' is called. |
186 | | - executor : concurrent.futures.Executor, or ipyparallel.Client, optional |
| 215 | + executor : concurrent.futures.Executor, distributed.Client, |
| 216 | + or ipyparallel.Client, optional |
187 | 217 | The executor in which to evaluate the function to be learned. |
188 | | - If not provided, a new ProcessPoolExecutor is used. |
| 218 | + If not provided, a new `ProcessPoolExecutor` is used on Unix systems |
| 219 | + while on Windows a `distributed.Client` is used if `distributed` is |
| 220 | + installed. |
189 | 221 | ntasks : int, optional |
190 | 222 | The number of concurrent function evaluations. Defaults to the number |
191 | 223 | of cores available in 'executor'. |
@@ -440,8 +472,9 @@ def shutdown(self, wait=True): |
440 | 472 |
|
441 | 473 | def _ensure_executor(executor): |
442 | 474 | if executor is None: |
443 | | - return concurrent.ProcessPoolExecutor() |
444 | | - elif isinstance(executor, concurrent.Executor): |
| 475 | + executor = _default_executor(**_default_executor_kwargs) |
| 476 | + |
| 477 | + if isinstance(executor, concurrent.Executor): |
445 | 478 | return executor |
446 | 479 | elif with_ipyparallel and isinstance(executor, ipyparallel.Client): |
447 | 480 | return executor.executor() |
|
0 commit comments