As Professor Kayvon mentioned in class: we should see if our system is computation or I/O heavy. In any case, we would want to use all of our resources (ie have one per core or per context).
A) If is it computation heavy, and we have too many worker processes like 2N, we may have processes waiting for a long process. We might also have trashing in our caching because of interleaving.
B) If it is I/O heavy, we definitely want to hide latency. The operations might be cheap though, so we don't want to spawn too many threads because that will be a lot of overhead relative to work and time going into serving the requests.
@makingthingsfast Regarding "we have too many worker processes like 2N, we may have processes waiting for a long process", I don't see why. Actually, I see the opposite, i.e. we want concurrency to avoid short requests waiting for long requests.
@365sleeping That also makes sense. I think it is also the case that there will be idle processes because of the high arithmetic intensity of the program, so we would not be making the best use of our resources.
Considering how the four factors affect N:
1. N must be at least the same as number of cores
2. N need to be larger than the number of cores
3. N need to be larger than the number of cores
4. N cannot be too large