You can do with a single optimizer in case you have ensembled the models as parts of a module like this:
class Net(nn.Module):
    
    def __init__(self):
        super(Net, self).__init__()

        self.model1=model1()
        self.model2=model2()

    def forward(self,x):
        return (self.model1(x)+self.model2(x))/2.0
        

But if you have defined 2 separate models and are ensembling them during training, you’d need an optimizer for each one.
A separate optimizer for each model will allow you to have separate learning rates and methodologies in an easier process as compared to a single optimizer.