#### Miscellaneous functions # According to https://github.com/pytorch/pytorch/issues/17199, this decorator # is necessary to make fork() and openmp work together. # # TODO: confirm if this is necessary for MXNet and Tensorflow. If so, we need # to standardize worker process creation since our operators are implemented with # OpenMP. import torch.multiprocessing as mp from _thread import start_new_thread from functools import wraps import traceback def thread_wrapped_func(func): """ Wraps a process entry point to make it work with OpenMP. """ @wraps(func) def decorated_function(*args, **kwargs): queue = mp.Queue() def _queue_result(): exception, trace, res = None, None, None try: res = func(*args, **kwargs) except Exception as e: exception = e trace = traceback.format_exc() queue.put((res, exception, trace)) start_new_thread(_queue_result, ()) result, exception, trace = queue.get() if exception is None: return result else: assert isinstance(exception, Exception) raise exception.__class__(trace) return decorated_function