Description of the problem
- The goal of the problem is to write a program on Windows to support processor utilization by about 50% .
- On Windows, we can use Task Manager or Perfmon.exe to monitor CPU usage.
- The percentage of processor usage should be about 50%, since the operating system has many other tasks, we just use the approximate percentage of processor usage.
- The CPU can be a multi-core processor or a single-core processor, so a universal solution is offered
Origin of the problem
The original question is from Chapter 1.1, The Beauty of Programming.
Personal effort on the issue
Wednesday
- Processor: Intel i5-3470, 4 cores, 4 threads.
- System: Windows 7
- Development environment: Visual Studio 2010, library support
First try
My first attempt did not take into account multicore and multithreading, so it did not work, but it gives an idea: if we want the processor to be half loaded, we could create an infinite loop that sleeps half the time and takes the processor to the other half.
I will just skip the details of the first attempt.
Second attempt
In my second attempt, everything went well, but there are still some problems that bother me .
My first decision
The following snippets are the first possible solution. It uses GetTickCount() from the Windows API and uses two threads to load the processor by 50%.
The solution is one value .
#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 was successful, but I donβt quite understand why I can only use two threads to get half the processor load, since the i5-3470 processor is a quad-core processor, theoretically I could only get the processor loaded at 25% using two threads.
Why am I using two threads instead of four threads?
At first I thought the processor was a dual-core XD processor.
Q1 : here is my first question: Why can two threads of this infiniteLoop() consume 50% of the capacity of the main core?
I tried very hard to understand this problem, but I really am not able to do it myself: X
My second decision
The second solution is exactly the same as the first, except that I use clock() from time.h to replace the GetTickCount() function. In this solution, I really need 4 threads to load the processor 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 overall processor utilization almost 50%, but, watching the task manager β performance β CPU, I find that the use of the four cores is not evenly distributed, the first two cores have a load of almost 60%, the third one is about 50%, and the last only about 30% of the maximum load.
So this is my second question.
Q2: Why are these kernels not evenly loaded, is there any mechanism inside the operating system behind this phenomenon?
My third decision
Another idea is to completely block two threads, thereby making the processor load 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(); }
Thought of Three Solutions
- These three solutions are not universal solutions for loading the processor by 50%, because if you have other programs running on the system, they will also consume processor capacity.
- The solution works only in a quad-core processor, if you want to use it on other processors, for example a dual-core processor, you need to change the thread number.
- None of these three solutions are elegant .. XD
So, Q3: can someone provide an elegant solution that could fulfill the goal and transfer between different types of processors?
Many thanks to those who read this question, and even much more thanks to those who can answer this question in advance!
Xd