A parallel version of the map function with a progress bar. Args: array (array-like): An array to iterate over. function (function): A python function to apply to the elements of array n_jobs (int, default=16): The number of cores to use
(array, function, n_jobs=16, use_kwargs=False, front_num=0)
| 2 | from concurrent.futures import ProcessPoolExecutor, as_completed |
| 3 | |
| 4 | def parallel_process(array, function, n_jobs=16, use_kwargs=False, front_num=0): |
| 5 | """ |
| 6 | A parallel version of the map function with a progress bar. |
| 7 | |
| 8 | Args: |
| 9 | array (array-like): An array to iterate over. |
| 10 | function (function): A python function to apply to the elements of array |
| 11 | n_jobs (int, default=16): The number of cores to use |
| 12 | use_kwargs (boolean, default=False): Whether to consider the elements of array as dictionaries of |
| 13 | keyword arguments to function |
| 14 | front_num (int, default=3): The number of iterations to run serially before kicking off the parallel job. |
| 15 | Useful for catching bugs |
| 16 | Returns: |
| 17 | [function(array[0]), function(array[1]), ...] |
| 18 | """ |
| 19 | # We run the first few iterations serially to catch bugs |
| 20 | if front_num > 0: |
| 21 | front = [function(**a) if use_kwargs else function(a) for a in array[:front_num]] |
| 22 | else: |
| 23 | front = [] |
| 24 | # If we set n_jobs to 1, just run a list comprehension. This is useful for benchmarking and debugging. |
| 25 | if n_jobs == 1: |
| 26 | return front + [function(**a) if use_kwargs else function(a) for a in tqdm(array[front_num:])] |
| 27 | # Assemble the workers |
| 28 | with ProcessPoolExecutor(max_workers=n_jobs) as pool: |
| 29 | # Pass the elements of array into function |
| 30 | if use_kwargs: |
| 31 | futures = [pool.submit(function, **a) for a in array[front_num:]] |
| 32 | else: |
| 33 | futures = [pool.submit(function, a) for a in array[front_num:]] |
| 34 | kwargs = { |
| 35 | 'total': len(futures), |
| 36 | 'unit': 'it', |
| 37 | 'unit_scale': True, |
| 38 | 'leave': True |
| 39 | } |
| 40 | # Print out the progress as tasks complete |
| 41 | for f in tqdm(as_completed(futures), **kwargs): |
| 42 | pass |
| 43 | out = [] |
| 44 | # Get the results from the futures. |
| 45 | for i, future in tqdm(enumerate(futures)): |
| 46 | try: |
| 47 | out.append(future.result()) |
| 48 | except Exception as e: |
| 49 | out.append(e) |
| 50 | return front + out |
no outgoing calls
no test coverage detected