|
193 | 193 | "outputs": [], |
194 | 194 | "source": [ |
195 | 195 | "#export\n", |
196 | | - "def check_parallel_num(param_name, num_workers):\n", |
197 | | - " if sys.platform == \"win32\" and IN_NOTEBOOK and num_workers > 0:\n", |
| 196 | + "def parallelable(param_name, num_workers, f=None):\n", |
| 197 | + " f_in_main = f == None or sys.modules[f.__module__].__name__ == \"__main__\" \n", |
| 198 | + " if sys.platform == \"win32\" and IN_NOTEBOOK and num_workers > 0 and f_in_main:\n", |
198 | 199 | " print(\"Due to IPython and Windows limitation, python multiprocessing isn't available now.\")\n", |
199 | | - " print(f\"So `{param_name}` is changed to 0 to avoid getting stuck\")\n", |
200 | | - " num_workers = 0\n", |
201 | | - " return num_workers" |
| 200 | + " print(f\"So `{param_name}` has to be changed to 0 to avoid getting stuck\")\n", |
| 201 | + " return False\n", |
| 202 | + " return True" |
202 | 203 | ] |
203 | 204 | }, |
204 | 205 | { |
|
263 | 264 | " \"Same as Python's ProcessPoolExecutor, except can pass `max_workers==0` for serial execution\"\n", |
264 | 265 | " def __init__(self, max_workers=defaults.cpus, on_exc=print, pause=0, **kwargs):\n", |
265 | 266 | " if max_workers is None: max_workers=defaults.cpus\n", |
266 | | - " max_workers = check_parallel_num('max_workers', max_workers)\n", |
267 | 267 | " store_attr()\n", |
268 | 268 | " self.not_parallel = max_workers==0\n", |
269 | 269 | " if self.not_parallel: max_workers=1\n", |
270 | 270 | " super().__init__(max_workers, **kwargs)\n", |
271 | 271 | "\n", |
272 | 272 | " def map(self, f, items, *args, timeout=None, chunksize=1, **kwargs):\n", |
| 273 | + " if not parallelable('max_workers', self.max_workers, f): self.max_workers = 0\n", |
| 274 | + " self.not_parallel = self.max_workers==0\n", |
| 275 | + " if self.not_parallel: self.max_workers=1\n", |
| 276 | + " \n", |
273 | 277 | " if self.not_parallel == False: self.lock = Manager().Lock()\n", |
274 | 278 | " g = partial(f, *args, **kwargs)\n", |
275 | 279 | " if self.not_parallel: return map(g, items)\n", |
|
340 | 344 | "metadata": {}, |
341 | 345 | "outputs": [], |
342 | 346 | "source": [ |
343 | | - "def add_one(x, a=1): \n", |
| 347 | + "#export\n", |
| 348 | + "def add_one(x, a=1):\n", |
| 349 | + " # this import is necessary for multiprocessing in notebook on windows\n", |
| 350 | + " import random\n", |
344 | 351 | " time.sleep(random.random()/80)\n", |
345 | | - " return x+a\n", |
346 | | - "\n", |
| 352 | + " return x+a" |
| 353 | + ] |
| 354 | + }, |
| 355 | + { |
| 356 | + "cell_type": "code", |
| 357 | + "execution_count": null, |
| 358 | + "metadata": {}, |
| 359 | + "outputs": [], |
| 360 | + "source": [ |
347 | 361 | "inp,exp = range(50),range(1,51)\n", |
348 | 362 | "\n", |
349 | 363 | "test_eq(parallel(add_one, inp, n_workers=2, progress=False), exp)\n", |
|
378 | 392 | "name": "stdout", |
379 | 393 | "output_type": "stream", |
380 | 394 | "text": [ |
381 | | - "0 2021-02-03 09:51:30.561681\n", |
382 | | - "1 2021-02-03 09:51:30.812066\n", |
383 | | - "2 2021-02-03 09:51:31.063662\n", |
384 | | - "3 2021-02-03 09:51:31.313478\n", |
385 | | - "4 2021-02-03 09:51:31.564776\n" |
| 395 | + "0 2021-02-23 06:38:58.778425\n", |
| 396 | + "1 2021-02-23 06:38:59.028804\n", |
| 397 | + "2 2021-02-23 06:38:59.280227\n", |
| 398 | + "3 2021-02-23 06:38:59.530889\n", |
| 399 | + "4 2021-02-23 06:38:59.781011\n" |
386 | 400 | ] |
387 | 401 | } |
388 | 402 | ], |
|
438 | 452 | "#export \n", |
439 | 453 | "def parallel_gen(cls, items, n_workers=defaults.cpus, **kwargs):\n", |
440 | 454 | " \"Instantiate `cls` in `n_workers` procs & call each on a subset of `items` in parallel.\"\n", |
441 | | - " n_workers = check_parallel_num('n_workers', n_workers)\n", |
| 455 | + " if not parallelable('n_workers', n_workers): n_workers = 0\n", |
442 | 456 | " if n_workers==0:\n", |
443 | 457 | " yield from enumerate(list(cls(**kwargs)(items)))\n", |
444 | 458 | " return\n", |
445 | 459 | " batches = L(chunked(items, n_chunks=n_workers))\n", |
446 | 460 | " idx = L(itertools.accumulate(0 + batches.map(len)))\n", |
447 | 461 | " queue = Queue()\n", |
448 | 462 | " if progress_bar: items = progress_bar(items, leave=False)\n", |
449 | | - " f=partial(_f_pg, cls(**kwargs), queue)\n", |
| 463 | + " f=partial(_f_pg, cls(**kwargs), queue) \n", |
450 | 464 | " done=partial(_done_pg, queue, items)\n", |
451 | 465 | " yield from run_procs(f, done, L(batches,idx).zip())" |
452 | 466 | ] |
|
546 | 560 | "Converted 05_transform.ipynb.\n", |
547 | 561 | "Converted 07_meta.ipynb.\n", |
548 | 562 | "Converted 08_script.ipynb.\n", |
549 | | - "Converted index.ipynb.\n" |
| 563 | + "Converted index.ipynb.\n", |
| 564 | + "Converted parallel_win.ipynb.\n" |
550 | 565 | ] |
551 | 566 | } |
552 | 567 | ], |
|
569 | 584 | "exit_code = process.wait()\n", |
570 | 585 | "test_eq(exit_code, 0)" |
571 | 586 | ] |
| 587 | + }, |
| 588 | + { |
| 589 | + "cell_type": "code", |
| 590 | + "execution_count": null, |
| 591 | + "metadata": {}, |
| 592 | + "outputs": [], |
| 593 | + "source": [] |
572 | 594 | } |
573 | 595 | ], |
574 | 596 | "metadata": { |
|
0 commit comments