Hi,
You should use save_for_backward() for any input or output and ctx. for everything else.
So in your case:
# In forward
ctx.res = res
ctx.save_for_backward(weights, Mpre)

# In backward
res = ctx.res
weights, Mpre = ctx.saved_tensors

If you do that, you won’t need to do del ctx.intermediate. It is the fact that you save some inputs in the ctx that create the memory leak.
And so you will be able to retain_graph=True.