Sorry for this very late reply.
I have to question your setup a bit, are you running 20 agents in 20 VMs on a single machine? The need for multiple agents is generally to distribute load to several physical machines when one isn't capable of generating enough load by itself. A single loadUI agent is capable of running several threads, as long as the hardware can support it. That said, loadUI doesn't really use the same thread model as many other load testing tools use, as it is not a very accurate representation of real world load, and isn't very efficient. Instead loadUI internally manages threads to provide the desired number of requests per second, or the desired number of concurrent requests (using the Fixed Load Generator). It sounds like you should be able to use a single loadUI agent with a rate 20 times higher than what you currently have. Again, since loadUI manages threads as efficiently as possible, if you're using for instance a "Fixed Rate" Generator it's likely that Thread 0 will handle most requests, and higher numbered threads will only be used if needed, so you won't get an even distribution of ThreadIndices.
One thing you should be able to use which is unique per machine is the hostname, which you can access using the following Property Expansion: ${=InetAddress.localHost.hostName}
If you need to make sure you have something unique for all agents and threads, you will have to combine the hostname and the thread index.
Regards,
Dain
eviware.com