All the methods using copy_ take some time to execute, especially on CPU this might be slow. Also the nn.Sequential() modules are slower than just executing them on the forward pass. I think this is due to some overhead that needs to be created when executing the Sequential module.
The extra time might come from accessing memory. Training on your CPU is slow because you are storing a lot of things in RAM because of the copy_ s and fetching data from RAM is very slow. On GPU you do not notice how slow it is because VRAM is much faster than RAM.
This are just some quick conclusions I drew by looking at your code, but I might be wrong. This is obviously added to the fact that training on CPU is much slower than on GPU due to the data parallelism that can only be achieved using GPU.