For optimal speed, I would suggest that you omit the softmax in the model, instead , return the output of fc3 and use nn.CrossEntropyLoss instead of F.nll_loss.
Furthermore, you should be aware that a task that takes between 0.6 - 3 secs per epoch is not a true test of speed. A number of performance optimizations might incur a slight overhead which would manifest strongly in a minimal task, however,  for a more expensive task, the performance would be significantly faster and the overhead would have no effect. I suggest you use CIFAR 10 with sufficient number of layers when doing performance comparisons.