At some point, the build system sees that some file says import MyModule;. When it sees that, the build system needs to go find the module for MyModule.
If MyModule has not yet been built, the build system needs to build it. To do that, it has to (among other things) scan all of the known source files in your project to see which ones are used to build MyModule. But the most important thing is that it needs to figure out which file it specifically needs to build in order for import MyModule to work right now.
That process works best and fastest if the system only needs to look for a single file to build (this way, the system can pre-process everything with a quick scanner to find all of those files). So the module system provides that: for any particular module, there is the primary module interface which defines everything that is exported by a module. Building that module may provoke the compilation of other modules, but we know which file has to be finished building before import MyModule can work.
Now sticking everything a module can export into just one file is not the best idea. So in many cases, you'll have multiple files that export stuff, and you'll export import them in your main MyModule primary interface file. But since module names are global, we don't want dozens of tiny module names cluttering up the namespace.
Enter module partitions: These are module interface files whose names are namespaced within a specific module. Module interface files can include other partitions, but only those within the same module. And obviously, the graph of partition inclusion must be acyclic.
But that leaves us with a small problem. Let's say you have a partition that defines a class that gets exported to the primary module interface. But you don't want to put the implementation of those member functions in that partition file. So... where does it go?
I mean, you could put it in another partition that doesn't get imported by anybody. But if that partition doesn't get imported... why bother giving it a partition name? It'd be best if you can communicate immediately that this "partition" cannot be included.
Enter module implementation units. They are part of a specific module, and therefore they can import partitions of that module. But they cannot themselves be imported by anyone.
That's what they're for.
But note that the build system knows that it doesn't need to build module implementation units in order to completely build the module. It only needs to build the primary module interface file and any partitions included by it (directly or indirectly). This allows module rebuilding to be as fast as possible if you put your implementations into implementation units.
Lastly, module implementation units (and interface units) have access to any names that they import from a partition which the partition does not export. These module-local names are only accessible within the module.