Write a program to use the processor About 50%

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

+6
source share
3 answers

I think the key that you are missing is the ability to get the number of processors. You can do it as follows:

 SYSTEM_INFO sysinfo; GetSystemInfo( &sysinfo ); numCPU = sysinfo.dwNumberOfProcessors; 

The counter will be the same as the number specified in the task manager.

If you combine this with existing approaches, you should get something pretty common.

+1
source
  • Q1 : the way how the transition from using GetTickCount() to clock() solved the problem, I think GetTickCount() does not work as expected, but I really can not understand why.
  • Q2 . If the thread does not start and does not end at exactly the same time, overlap occurs, so it can be, for example, thread 3 starts while thread 1 is waiting and it appears on core 1 (available because thread 1 is suspended).
  • Q3 . I think, as Baldrick said, by getting the number of cores and creating the right number of threads, you will make your second decision fairly general.
+1
source

In Q1: It seems that the resolution of GetTickCount () is more than 10 ms. At least on my box 77 based on the i7 860 at work.

 #include "stdafx.h" #include <iostream> #include <windows.h> int _tmain(int argc, _TCHAR* argv[]) { while(1) { std::cout <<GetTickCount() << std::endl; } return 0; } 

Some output:

510948811 510948811 510948811 510948811 510948811 510948811 510948811 510948811 510948811 510948811 510948811 510948826 510948826 510948826 510948826 510948826 510948826 510948826 510948826 510948826 510948826 510948826 510948826 510948826 510948826 510948826 510948826 510948826 510948826 510948826 510948826 510948826 510948826 510948826 510948826 510948826 510948826 510948826 510948826 510948826 510948826 510948826 510948826 510948826 510948826 510948826 510948842 510948842 510948842 510948842 510948842 510948842

Although then I expect that you will get from 25% to 50% of the use.

Edit: I created a project using your code for Q1 on my i7, adjusted the code to 4 threads, and I see 50% use. Interesting.

Edit2: If you space in the first code example to 30, I get the expected behavior.

0
source

Source: https://habr.com/ru/post/957919/


All Articles