Multiprocessing allows you to use all cores, but you can't share memory like in threads. So you have to Serialize/Deserialize a lot for exchange data.
If your serializations cost are low and need computation power, you should use multiprocessing. If you are just waiting I/O you can use threads.
BTW, modern python "ProcessPoolExecutor" is not designed for compute heavy batch like "Pool" from "multiprocessing".
But if you meant semantically equivalent, no they aren't - threading is shared memory and multiprocessing is message passing. If you were to draw a tree of approaches to concurrency and parallelism, you would probably make this division the root node bisecting the domain into two - it's the two fundamental approaches to doing concurrency.
Those that cross between the two are usually notable for doing that and describe themselves as a hybrid approach.
I think it divides the literature pretty cleanly in two.
In most cases, yes. You can use shared memory buffers for IPC, though, although it typically requires more effort.