virtualizationcpu-coreshyperthreading

Weight-factor to determine Virtual Cores for a Virtual Machine


I have to design an algorithm which will decide to assign virtual cores to a VM.

e.g. I have 2 options to create a machines. That could be physical/virtual. Let's consider 2 cases:

I want to make sure that from you that, is this a correct way to scale the required processing capabilities by the use of a weight-factor, in the case of virtual-machines.

If yes, are there any related studies or proof of concepts to use this mechanism of determining the number of processors required for a virtual-machine?


Solution

  • In general; for SMT (e.g. hyper-threading) on 80x86 CPUs; with all logical CPUs within a core doing work:

    Note that this may also apply to AMD's Bulldozer (even though it's not considered SMT), where the FPU is shared between cores but the rest of the core is not (in other words, if both cores are pounding the FPU at the same time then performance of both cores will be effected).

    This means that (e.g.) for a 2.3 GHz core with 2 logical CPUs per core, each logical CPU may get (the crude equivalent of) anything from 0.75 GHz to 3.4 Ghz; depending on the exact code that each logical CPU happens to be executing and various power management conditions (thermal throttling, turbo-boost, etc).

    However, actual performance also depends on things like caches (and cache sharing), RAM chip bandwidth, and virtual machine overheads (which vary from "extreme" for code causing a huge number of VMEXITs to almost nothing). With this in mind (e.g.) for a 2.3 GHz core, each logical CPU may get (the crude equivalent of) anything from a few hundred MHz to 3.4 Ghz; depending on many factors.

    Essentially; your "weight" should be any random number from 0.1 to 1.0 depending on a bunch of stuff that you can't/won't know.

    Fortunately, any code running inside the virtual machine is likely to be designed to handle a wide variety of different CPUs each with a wide variety of speeds; so it's enough to just assign any CPU to the virtual machine and let the software running inside the virtual machine adapt to whatever performance it was given.

    Alternatively (if you need to guarantee some kind of performance or you want to try to hide the timing differences so that code in the VM doesn't know it's not running on real hardware); you can keep track of "virtual time" and "wall clock time" and try to keep these times roughly in sync. For example, if "virtual time" is moving too slow (e.g. because the code inside the VM is causing lots of VMEXITs) you can pretend that the virtual CPU got hot and started thermal throttling to create a plausible/realistic excuse that allows "virtual time" to catch up to "wall clock time"; and if something can happen sooner than it should (e.g. you know that guest is waiting for a virtual timer that will expire in 100 milliseconds and can pretend that 100 milliseconds passed when it didn't) you can deliberately slow down the virtual machine until "wall clock time" catches up to "virtual time". In this case it would be a good idea to give yourself some room to move (pretend the virtual CPU is slower than it could be, because it's easier to slow the virtual machine down than it is to speed it up). Of course this can also be used to hide timing differences caused by SMT, and can hide timing difference caused by sharing CPUs between VMs (e.g. when there's more virtual cores than real cores).

    Note: The "alternative alternative" is to say that "virtual time" has nothing to do with "wall clock time" at all. This allows you to (e.g.) emulate a 6 GHz CPU when all you have is an old 1 GHz CPU - it'd just mean that 1 "virtual second" takes about 6 "wall clock seconds".

    Also note that with all the security problems in the last 18+ months (e.g. spectre) I'd strongly consider using "cores" as the minimum assignable unit, such that at any point in time a VM gets all logical CPUs belonging to a core or none of the logical CPUs belonging to the core (and refuse to allow logical CPUs within the same core to be assigned to different virtual machines at the same time, because data will probably leak across any of the many side-channels from one VM to another).