Problem Description
- The goal of the problem is to write a program on Windows to keep the CPU usage at about 50% percent.
- On Windows we can use Task Manager or Perfmon.exe to monitor the CPU usage.
- The CPU usage percentage should be near 50%, since there're many other tasks in the operating system, we just take the approximate usage percent of the CPU.
- The CPU could be a multiple core processor or a single core processor, so a generic solution is favored
Origin of The Problem
The original question is from chapter 1.1 of Beauty of Programming
Personal Efforts On The Problem
Environments
- Processor: Intel i5-3470, 4 cores, 4 threads
- System: Windows 7
- Development Environment: Visual Studio 2010, boost library
First Try
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.
Second Try
In my second effort, things went well, but there're still some problems that bothers me.
My First Solution
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
My Second Solution
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?
My Third Solution
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();
}
Thought About The Three Solutions
- Those three solutions are not generic solutions to get CPU loaded at 50%, since if you have other programs running in the system, they will also consume CPU capacity.
- The solution only works in quad-core processor, if you want to use it on other processors, for example, dual-core processor, you have to modify the number of the thread.
- None of these three solutions is elegant..XD
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
infiniteLoopreally sleeps for about 50% of the thread time. One thread takes one core's 50% capacity, two threads will make it 100% capacity, and that's 25% capacity of a quad-core processor instead of 50%, isn't it?whileloop, becauseGetTickCount() - startTime <= INTERVALsays to the thread: you cannot jump out of the loop until INTERVAL(10) milliseconds has passed. After 10 milliseconds, the thread will then sleep for 10 milliseconds due to the next two statements.