The original question is from chapter 1.1 of Beauty of Programming
My first try didn't put multicore and multithread in consideration, so it didn't work, but it provides the idea: if we want the processor half loaded, we could create a infinite loop which sleeps half of the time, and occupies the processor the other half.
I'll just skip the detail of first try.
In my second effort, things went well, but there're still some problems that bothers me.
The following snippets is the first possible solution. It uses GetTickCount()
from Windows API, and uses two threads to get the processor loaded at 50%.
The solution one gist.
#include <boost/thread.hpp>
#include "windows.h"
#define INTERVAL 10
void infiniteLoop() {
while (1) {
DWORD startTime = GetTickCount();
while (GetTickCount() - startTime <= INTERVAL)
;
boost::posix_time::millisec sleepTime(INTERVAL);
boost::this_thread::sleep(sleepTime);
}
}
int main() {
boost::thread thread1(infiniteLoop);
boost::thread thread2(infiniteLoop);
thread1.join();
thread2.join();
char c;
std::cin >> c;
}
The solution is successful, but I don't quite understand why I can use only two thread to get CPU half loaded, since i5-3470 processor is a quad-core processor, theoretically, I could only get the processor loaded at 25% using two threads.
Why I use two threads instead of four threads?
At first, I thought the processor is a dual-core processor, XD.
Q1: here is my first question: Why two threads of this infiniteLoop()
could consume 50% of a qual-core CPU capacity?
I tried hard to figure this problem out, but I'm really not capable to do it myself.. :X
The second solution is exactly the same as the first one, except that I use clock()
from time.h
to replace GetTickCount()
function. In this solution, I really needs 4 threads to get the processor loaded at 50%.
Here is the code.
#include <boost/thread.hpp>
#include "windows.h"
#include <ctime>
#define INTERVAL 10
void infiniteLoop() {
while (1) {
clock_t startTime = clock();
while (clock() - startTime <= INTERVAL)
;
boost::posix_time::millisec sleepTime(INTERVAL);
boost::this_thread::sleep(sleepTime);
}
}
int main() {
boost::thread thread1(infiniteLoop);
boost::thread thread2(infiniteLoop);
boost::thread thread3(infiniteLoop);
boost::thread thread4(infiniteLoop);
thread1.join();
thread2.join();
thread3.join();
thread4.join();
char c;
std::cin >> c;
}
This solution makes the total usage of the processor almost at 50%, but by observing task manager->performance->CPU record, I find that the usage of four cores is not uniformly distributed, the first two cores have a load of almost 60%, the third one is about 50%, and the last one is merely about 30% of the maximum load.
So it's my second question.
Q2: Why are those cores not uniformly loaded, does there exist some mechanism inside the operating system behind this phenomenon?
Another idea is to totally block two threads, thus making the CPU loaded at 50%.
Here is the code.
#include <boost/thread.hpp>
#include "windows.h"
#include <iostream>
void infiniteRunningLoop() {
while (1) {
;
}
}
int main() {
boost::thread thread1(infiniteRunningLoop)
boost::thread thread2(infiniteRunningLoop)
thread1.join();
thread2.join();
}
So, Q3: Could someone provides an elegant solution that could fulfill the target and is portable among different kinds of processors?
Many thanks to those who read through the question, and even lots more thanks to those who may answer this question in advance!
XD
For less demanding games, if you are running a PC with an SSD, decent GPU like GTX 1660 and Ryzen 5 CPU (or another brand equivalent), the CPU usage from 10% to 30% is normal. For more demanding games, the CPU usage can be from 30% to 70%.
It is normal for it to be high because the processor is not doing much at the moment. So, if your System Idle process is using 60% - 70% of your CPU, it means you're actually using 40% - 30% of it. Was this reply helpful? No the System Idle Process is only using 20-30% when running no or very few programs.
I think the key thing you are missing is the ability to get a count of the number of processors. You can do it like this:
SYSTEM_INFO sysinfo;
GetSystemInfo( &sysinfo );
numCPU = sysinfo.dwNumberOfProcessors;
The count from this will be the same as the number you see listed in Task Manager.
If you combine this with your existing approaches, you should get something quite generic working.
GetTickCount()
to clock()
solved the problem, I guess GetTickCount()
doesn't work as expected, but I really can't think why.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With