Hi,
For case 3 you don’t actually need create_graph=True, only retain_graph=True right?
It’s because, your parameters in model2 still require gradients. So when extra is computed, it requires gradient. When extra is then used in the loop, this same section of the graph (corresponding to the computations that happened in model2) are shared between the different iterations. And so you need to tell the engine not to free them if you need to reuse them.
If in your case, you don’t need gradient when doing the forward of a given model, you have 2 options:

If it’s temporary and the input does not require gradients, you can encase the forward in a no_grad block:

with torch.no_grad():
    extra = model2(data)


If it’s permanent, you can also iterate over each parameter in model2 and mark it as requires_grad=False.