|
import contextlib |
|
import importlib |
|
|
|
import torch |
|
import intel_extension_for_pytorch as ipex |
|
|
|
|
|
|
|
|
|
class CondFunc: |
|
def __new__(cls, orig_func, sub_func, cond_func): |
|
self = super(CondFunc, cls).__new__(cls) |
|
if isinstance(orig_func, str): |
|
func_path = orig_func.split(".") |
|
for i in range(len(func_path) - 1, -1, -1): |
|
try: |
|
resolved_obj = importlib.import_module(".".join(func_path[:i])) |
|
break |
|
except ImportError: |
|
pass |
|
for attr_name in func_path[i:-1]: |
|
resolved_obj = getattr(resolved_obj, attr_name) |
|
orig_func = getattr(resolved_obj, func_path[-1]) |
|
setattr( |
|
resolved_obj, |
|
func_path[-1], |
|
lambda *args, **kwargs: self(*args, **kwargs), |
|
) |
|
self.__init__(orig_func, sub_func, cond_func) |
|
return lambda *args, **kwargs: self(*args, **kwargs) |
|
|
|
def __init__(self, orig_func, sub_func, cond_func): |
|
self.__orig_func = orig_func |
|
self.__sub_func = sub_func |
|
self.__cond_func = cond_func |
|
|
|
def __call__(self, *args, **kwargs): |
|
if not self.__cond_func or self.__cond_func(self.__orig_func, *args, **kwargs): |
|
return self.__sub_func(self.__orig_func, *args, **kwargs) |
|
else: |
|
return self.__orig_func(*args, **kwargs) |
|
|
|
|
|
_utils = torch.utils.data._utils |
|
|
|
|
|
def _shutdown_workers(self): |
|
if ( |
|
torch.utils.data._utils is None |
|
or torch.utils.data._utils.python_exit_status is True |
|
or torch.utils.data._utils.python_exit_status is None |
|
): |
|
return |
|
if hasattr(self, "_shutdown") and not self._shutdown: |
|
self._shutdown = True |
|
try: |
|
if hasattr(self, "_pin_memory_thread"): |
|
self._pin_memory_thread_done_event.set() |
|
self._worker_result_queue.put((None, None)) |
|
self._pin_memory_thread.join() |
|
self._worker_result_queue.cancel_join_thread() |
|
self._worker_result_queue.close() |
|
self._workers_done_event.set() |
|
for worker_id in range(len(self._workers)): |
|
if self._persistent_workers or self._workers_status[worker_id]: |
|
self._mark_worker_as_unavailable(worker_id, shutdown=True) |
|
for w in self._workers: |
|
w.join(timeout=torch.utils.data._utils.MP_STATUS_CHECK_INTERVAL) |
|
for q in self._index_queues: |
|
q.cancel_join_thread() |
|
q.close() |
|
finally: |
|
if self._worker_pids_set: |
|
torch.utils.data._utils.signal_handling._remove_worker_pids(id(self)) |
|
self._worker_pids_set = False |
|
for w in self._workers: |
|
if w.is_alive(): |
|
w.terminate() |
|
|
|
|
|
class DummyDataParallel( |
|
torch.nn.Module |
|
): |
|
def __new__( |
|
cls, module, device_ids=None, output_device=None, dim=0 |
|
): |
|
if isinstance(device_ids, list) and len(device_ids) > 1: |
|
print("IPEX backend doesn't support DataParallel on multiple XPU devices") |
|
return module.to("xpu") |
|
|
|
|
|
def return_null_context(*args, **kwargs): |
|
return contextlib.nullcontext() |
|
|
|
|
|
def check_device(device): |
|
return bool( |
|
(isinstance(device, torch.device) and device.type == "cuda") |
|
or (isinstance(device, str) and "cuda" in device) |
|
or isinstance(device, int) |
|
) |
|
|
|
|
|
def return_xpu(device): |
|
return ( |
|
f"xpu:{device[-1]}" |
|
if isinstance(device, str) and ":" in device |
|
else ( |
|
f"xpu:{device}" |
|
if isinstance(device, int) |
|
else torch.device("xpu") if isinstance(device, torch.device) else "xpu" |
|
) |
|
) |
|
|
|
|
|
def ipex_no_cuda(orig_func, *args, **kwargs): |
|
torch.cuda.is_available = lambda: False |
|
orig_func(*args, **kwargs) |
|
torch.cuda.is_available = torch.xpu.is_available |
|
|
|
|
|
original_autocast = torch.autocast |
|
|
|
|
|
def ipex_autocast(*args, **kwargs): |
|
if len(args) > 0 and args[0] == "cuda": |
|
return original_autocast("xpu", *args[1:], **kwargs) |
|
else: |
|
return original_autocast(*args, **kwargs) |
|
|
|
|
|
original_torch_cat = torch.cat |
|
|
|
|
|
def torch_cat(tensor, *args, **kwargs): |
|
if len(tensor) == 3 and ( |
|
tensor[0].dtype != tensor[1].dtype or tensor[2].dtype != tensor[1].dtype |
|
): |
|
return original_torch_cat( |
|
[tensor[0].to(tensor[1].dtype), tensor[1], tensor[2].to(tensor[1].dtype)], |
|
*args, |
|
**kwargs, |
|
) |
|
else: |
|
return original_torch_cat(tensor, *args, **kwargs) |
|
|
|
|
|
original_interpolate = torch.nn.functional.interpolate |
|
|
|
|
|
def interpolate( |
|
tensor, |
|
size=None, |
|
scale_factor=None, |
|
mode="nearest", |
|
align_corners=None, |
|
recompute_scale_factor=None, |
|
antialias=False, |
|
): |
|
if antialias or align_corners is not None: |
|
return_device = tensor.device |
|
return_dtype = tensor.dtype |
|
return original_interpolate( |
|
tensor.to("cpu", dtype=torch.float32), |
|
size=size, |
|
scale_factor=scale_factor, |
|
mode=mode, |
|
align_corners=align_corners, |
|
recompute_scale_factor=recompute_scale_factor, |
|
antialias=antialias, |
|
).to(return_device, dtype=return_dtype) |
|
else: |
|
return original_interpolate( |
|
tensor, |
|
size=size, |
|
scale_factor=scale_factor, |
|
mode=mode, |
|
align_corners=align_corners, |
|
recompute_scale_factor=recompute_scale_factor, |
|
antialias=antialias, |
|
) |
|
|
|
|
|
original_linalg_solve = torch.linalg.solve |
|
|
|
|
|
def linalg_solve(A, B, *args, **kwargs): |
|
if A.device != torch.device("cpu") or B.device != torch.device("cpu"): |
|
return_device = A.device |
|
return original_linalg_solve(A.to("cpu"), B.to("cpu"), *args, **kwargs).to( |
|
return_device |
|
) |
|
else: |
|
return original_linalg_solve(A, B, *args, **kwargs) |
|
|
|
|
|
def ipex_hijacks(): |
|
CondFunc( |
|
"torch.Tensor.to", |
|
lambda orig_func, self, device=None, *args, **kwargs: orig_func( |
|
self, return_xpu(device), *args, **kwargs |
|
), |
|
lambda orig_func, self, device=None, *args, **kwargs: check_device(device), |
|
) |
|
CondFunc( |
|
"torch.Tensor.cuda", |
|
lambda orig_func, self, device=None, *args, **kwargs: orig_func( |
|
self, return_xpu(device), *args, **kwargs |
|
), |
|
lambda orig_func, self, device=None, *args, **kwargs: check_device(device), |
|
) |
|
CondFunc( |
|
"torch.empty", |
|
lambda orig_func, *args, device=None, **kwargs: orig_func( |
|
*args, device=return_xpu(device), **kwargs |
|
), |
|
lambda orig_func, *args, device=None, **kwargs: check_device(device), |
|
) |
|
CondFunc( |
|
"torch.load", |
|
lambda orig_func, *args, map_location=None, **kwargs: orig_func( |
|
*args, return_xpu(map_location), **kwargs |
|
), |
|
lambda orig_func, *args, map_location=None, **kwargs: map_location is None |
|
or check_device(map_location), |
|
) |
|
CondFunc( |
|
"torch.randn", |
|
lambda orig_func, *args, device=None, **kwargs: orig_func( |
|
*args, device=return_xpu(device), **kwargs |
|
), |
|
lambda orig_func, *args, device=None, **kwargs: check_device(device), |
|
) |
|
CondFunc( |
|
"torch.ones", |
|
lambda orig_func, *args, device=None, **kwargs: orig_func( |
|
*args, device=return_xpu(device), **kwargs |
|
), |
|
lambda orig_func, *args, device=None, **kwargs: check_device(device), |
|
) |
|
CondFunc( |
|
"torch.zeros", |
|
lambda orig_func, *args, device=None, **kwargs: orig_func( |
|
*args, device=return_xpu(device), **kwargs |
|
), |
|
lambda orig_func, *args, device=None, **kwargs: check_device(device), |
|
) |
|
CondFunc( |
|
"torch.tensor", |
|
lambda orig_func, *args, device=None, **kwargs: orig_func( |
|
*args, device=return_xpu(device), **kwargs |
|
), |
|
lambda orig_func, *args, device=None, **kwargs: check_device(device), |
|
) |
|
CondFunc( |
|
"torch.linspace", |
|
lambda orig_func, *args, device=None, **kwargs: orig_func( |
|
*args, device=return_xpu(device), **kwargs |
|
), |
|
lambda orig_func, *args, device=None, **kwargs: check_device(device), |
|
) |
|
|
|
CondFunc( |
|
"torch.Generator", |
|
lambda orig_func, device=None: torch.xpu.Generator(device), |
|
lambda orig_func, device=None: device is not None |
|
and device != torch.device("cpu") |
|
and device != "cpu", |
|
) |
|
|
|
CondFunc( |
|
"torch.batch_norm", |
|
lambda orig_func, input, weight, bias, *args, **kwargs: orig_func( |
|
input, |
|
( |
|
weight |
|
if weight is not None |
|
else torch.ones(input.size()[1], device=input.device) |
|
), |
|
( |
|
bias |
|
if bias is not None |
|
else torch.zeros(input.size()[1], device=input.device) |
|
), |
|
*args, |
|
**kwargs, |
|
), |
|
lambda orig_func, input, *args, **kwargs: input.device != torch.device("cpu"), |
|
) |
|
CondFunc( |
|
"torch.instance_norm", |
|
lambda orig_func, input, weight, bias, *args, **kwargs: orig_func( |
|
input, |
|
( |
|
weight |
|
if weight is not None |
|
else torch.ones(input.size()[1], device=input.device) |
|
), |
|
( |
|
bias |
|
if bias is not None |
|
else torch.zeros(input.size()[1], device=input.device) |
|
), |
|
*args, |
|
**kwargs, |
|
), |
|
lambda orig_func, input, *args, **kwargs: input.device != torch.device("cpu"), |
|
) |
|
|
|
|
|
CondFunc( |
|
"torch.nn.modules.GroupNorm.forward", |
|
lambda orig_func, self, input: orig_func( |
|
self, input.to(self.weight.data.dtype) |
|
), |
|
lambda orig_func, self, input: input.dtype != self.weight.data.dtype, |
|
) |
|
CondFunc( |
|
"torch.nn.modules.linear.Linear.forward", |
|
lambda orig_func, self, input: orig_func( |
|
self, input.to(self.weight.data.dtype) |
|
), |
|
lambda orig_func, self, input: input.dtype != self.weight.data.dtype, |
|
) |
|
CondFunc( |
|
"torch.nn.modules.conv.Conv2d.forward", |
|
lambda orig_func, self, input: orig_func( |
|
self, input.to(self.weight.data.dtype) |
|
), |
|
lambda orig_func, self, input: input.dtype != self.weight.data.dtype, |
|
) |
|
CondFunc( |
|
"torch.nn.functional.layer_norm", |
|
lambda orig_func, input, normalized_shape=None, weight=None, *args, **kwargs: orig_func( |
|
input.to(weight.data.dtype), normalized_shape, weight, *args, **kwargs |
|
), |
|
lambda orig_func, input, normalized_shape=None, weight=None, *args, **kwargs: weight |
|
is not None |
|
and input.dtype != weight.data.dtype, |
|
) |
|
|
|
|
|
if not torch.xpu.has_fp64_dtype(): |
|
CondFunc( |
|
"torch.from_numpy", |
|
lambda orig_func, ndarray: orig_func(ndarray.astype("float32")), |
|
lambda orig_func, ndarray: ndarray.dtype == float, |
|
) |
|
|
|
|
|
CondFunc( |
|
"torch.utils.data.dataloader._BaseDataLoaderIter.__init__", |
|
lambda orig_func, *args, **kwargs: ipex_no_cuda(orig_func, *args, **kwargs), |
|
lambda orig_func, *args, **kwargs: True, |
|
) |
|
|
|
|
|
torch.utils.data.dataloader._MultiProcessingDataLoaderIter._shutdown_workers = ( |
|
_shutdown_workers |
|
) |
|
torch.nn.DataParallel = DummyDataParallel |
|
torch.autocast = ipex_autocast |
|
torch.cat = torch_cat |
|
torch.linalg.solve = linalg_solve |
|
torch.nn.functional.interpolate = interpolate |
|
torch.backends.cuda.sdp_kernel = return_null_context |
|
|