I have learned how to create and manage threads in C++. Now I'm trying to create game loop based on multithreading but I can't imagine how should I split whole game to tasks. I mean, should rendering be separated from updating physics?
First of all, heed the warning by DMGregory in the comments to the question. Multithreading is an evil source of weird, randomly appearing and impossible to reproduce bugs. Do not use it unless you know you have a performance problem and you already exhausted all other options of optimization.
Unfortunately there is no easy answer to the question which game features to parallelize and which not, because every game is different. But the general rule of thumb is that you want to parallelize tasks which are very CPU-intense, can be separated into independent units of computation and do not write any data to memory which is used by the other units of computation. The reason for this is that whenever you have one thread reading data another thread is writing, you might once in a while hit a weird race-condition where you are reading an intermediate state of the old and the new data.
For example, if you want to do route finding on a complex nav-mesh for 10000 actors at once, you might be able to multithread that by having 4 threads process 2500 actors each. But only if your actors don't communicate the results of their route-finding to each other and no unit actually executes a move until all threads have finished calculating their routes. Make sure to join all threads before you continue.
Regarding separating game mechanics from rendering: I would usually advise against this stunt, for the reason described above: Race Conditions. If you do this naively, then your rendering loop might from time to time end up rendering an object which is half in the previous frame and half in the next frame, which can manifest as really weird graphic glitches. Also, keep in mind that the heavy lifting of rendering usually happens mostly on the GPU, not the CPU, and those computations are asynchronous anyway. So the benefit of this is in many cases dubious anyway.
But if you do something in your rendering loop which is unusually CPU-intense and you really want to do this, you can avoid those race conditions by using a double-buffering strategy on your game-state. Have two copies of your game-state. While state A is rendered, your game loop calculates a new game-state B. When both the rendering-thread and the game-thread are finished, you switch the two states. game-state B is rendered while a new game-state A is calculated based on B. The same strategy can be used to execute any other game systems in parallel, as long as no two game systems need write-access to the same data-structure of the new game-state.
Another problem you should keep being aware of is that creating, managing and switching between threads is quite expensive on most operating systems. For that reason you should avoid creating short-lived threads and you should never have more threads than you have CPU cores (unless they are threads which idle most of the time, like a network listener or a file reading thread).