I think the general setup of the loss calculation just uses large tensors and thus a lot of memory.
You can add print statements to check the memory usage, e.g. via:
print(torch.cuda.memory_allocated()/1024**2)

batch_size = 1
n_classes = 10

pred = torch.randn(batch_size, n_classes, 160, 192, 160, device='cuda')
target = torch.randint(0, 2, (batch_size, 160, 192, 160), device='cuda')
print(torch.cuda.memory_allocated()/1024**2)

target_1_hot = torch.eye(n_classes)[target].type(pred.type()).to(pred.device)
target_1_hot = target_1_hot.permute(0, 4, 1, 2, 3)
print(torch.cuda.memory_allocated()/1024**2)

probas = torch.softmax(pred, dim=1)
print(torch.cuda.memory_allocated()/1024**2)

loss = 0.
eps = 1e-6
batch_size = len(probas)
for b in range(batch_size): # for loop but for this issue, batch_size is 1 in fact.
    intersections = torch.sum(probas[b, :] * target_1_hot[b, :], (1, 2, 3))
    cardinalities = torch.sum(probas[b, :] + target_1_hot[b, :], (1, 2, 3)) + eps
    loss += (1 - 2 * torch.sum(intersections / cardinalities))
print(torch.cuda.memory_allocated()/1024**2)

Using this code snippet you’ll get:
0.0
226.0
414.0
602.0
602.00146484375

A simple way to save some memory would be to e.g. reassign pred in:
pred = torch.softmax(pred, dim=1)

and use it in the following calculations, which would save approx. 180MB in this use case.