The reason why you are seeing inaccurate results on a real backend is because of the SWAP gates. In the current quantum computing hardware that IBM uses, the dominant source of noise is because of multi-qubit gates like CX and SWAP (also CSWAP). This is because the multi-qubit gates that act on multiple qubits suffer from errors and noise that depend on all the physical qubits being used for that gate. So noise and error rates for multi-qubit
gates are typically higher than those of single-qubit gates, so a circuit consisting of multi-qubit gates will experience more noise than a circuit of the same number of single qubit gates. And due to this reason the transpilers in qiskit will try to avoid using multi-qubit gates as much as possible.
So if you redesign your circuit (or use a pass manager in qiskit) to have less number of CSWAP gates then your circuit will be less prone to errors and noise.
Now coming to your concern of why you are seeing different results between a fake backend and a real backend. This is what qiskit documentation says about fake backend:
Fake backends: The fake backends in qiskit_ibm_runtime.fake_provider
mimic the behaviors of IBM Quantum™ systems by using system snapshots.
The system snapshots contain important information about the quantum
system, such as the coupling map, basis gates, and qubit properties,
which are useful for testing the transpiler and performing noisy
simulations of the system. The noise model from the snapshot is
automatically applied during simulation.
This means that the error rates and noise that are programmed into a fake backend only represent a snapshot of what you would actually see on a real device, whereas on a real device the error rates and noise can dynamically change and also the qubits experience more cross-talk due to the interference
with other qubits in close vicinity. So if you have more number of multi-qubit gates then your circuit will be more prone to error.