import random
import numpy as np
import torch

def get_total_trainable_params(model):
    return sum(p.numel() for p in model.parameters() if p.requires_grad)

def print_trainable_params_per_layer(model):
    for name, param in model.named_parameters():
        if param.requires_grad:
            print(name, param.data.shape)
            
def set_seeds(seed, cuda_deterministic=False):
    if seed is not None:
        random.seed(seed)
        np.random.seed(seed)
        torch.manual_seed(seed)
        if torch.cuda.is_available():
            torch.cuda.manual_seed(seed)
            torch.cuda.manual_seed_all(seed)
            if cuda_deterministic:
                torch.backends.cudnn.deterministic = True
                torch.backends.cudnn.benchmark = False

