import torch
import GPUtil
import gc
from inspect import getframeinfo


def gpu_show(frame):
    gc.collect(); torch.cuda.empty_cache()
    frameinfo = getframeinfo(frame)
    print(frameinfo.filename, frameinfo.lineno)
    GPUtil.showUtilization(all=True)


is_m_nan = lambda x: torch.tensor([torch.isnan(p).any() for p in x.parameters()]).any()
is_m_inf = lambda x: torch.tensor([torch.isinf(p).any() for p in x.parameters()]).any()


def is_mg_nan(x):
    result = list()
    for p in x.parameters():
        r = torch.isnan(p.grad).any() if p.grad is not None else False
        result.append(r)
    return torch.tensor(result).any()


def is_mg_inf(x):
    result = list()
    for p in x.parameters():
        r = torch.isinf(p.grad).any() if p.grad is not None else False
        result.append(r)
    return torch.tensor(result).any()


is_m = lambda x: is_m_nan(x) or is_m_inf(x) or is_mg_nan(x) or is_mg_inf(x)


def is_ts(ts):
    for t in ts:
        if torch.isnan(t).any() or torch.isinf(t).any():
            return True
    return False


def equal_m(m1, m2):
    for p1, p2 in zip(m1.parameters(), m2.parameters()):
        if p1.data.ne(p2.data).sum() > 0:
            return False
    return True


