Let the multi-core CPU usage curve listen to your command (implemented in Windows) -- The beauty of programming 1.1 Study Notes

Source: Internet
Author: User
Let the multi-core CPU usage curve listen to your command-the beauty of programming 1.1 Study Notes Problem:

Write a program to determine the CPU usage of the Windows Task Manager. There are several situations:

1. The CPU usage is fixed at 50%, which is a straight line;

2. the CPU usage is a straight line. The specific usage is determined by the command line parameters (range: 1 ~ 100 );

3. The CPU usage status is a sine curve.

Analysis and Solution:

(1) by observing the task manager, it is updated about once every 1 s. When the CPU usage is 0, the System Idle Process occupies the Idle time of the CPU.

When the CPU is idle, system idle process issues an idle command to suspend the CPU (temporarily stop working), which can effectively reduce the CPU kernel temperature and cannot be terminated. The CPU usage value in this process is not the actual CPU usage, but the CPU idle rate. That is to say, the larger the value, the higher the CPU idle rate, on the other hand, the CPU usage is higher. In Linux, the corresponding process is INIT and PID is 1.

 

When a process in the system is waiting for user input, or waiting for some events to occur (sending an I/O Request to wait for I/O response), or actively enters the Sleep state (such as Sleep ()).

In a refresh cycle in the task manager, the ratio of the CPU busy (executing the application) Time to the total time of the refresh cycle is the CPU usage. It displays the average CPU usage statistics for each refresh cycle. We can write a program to make it busy and idle for a while during the refresh time of the task manager. by adjusting the proportion of busy and idle, we can control the CPU usage displayed in the task manager.

 

The code in the book takes single-core CPU as the premise, but for multi-core CPU, the same process may be allocated to different cores by the CPU task distributor for execution, therefore, the task manager cannot achieve the expected results. Open the task manager to view multiple CPU usage records. My computer CPU is Core i5 450 M, dual-Core 4 threads. In the OS view, it works just like four CPUs. My task manager has four CPU usage records.

The so-called hyper-Threading Technology is to use special hardware commands to simulate two logical kernels inside the multi-thread processor into two physical chips, so that a single processor can "enjoy" the thread-Level Parallel Computing processor technology. Multithreading technology can effectively enhance the processing capability of the processor in multi-task and multi-thread processing on the operating systems and software supporting multithreading.

 

You can use the SetProcessAffinityMask () function to run a specified process on a specific processor.

Bool setprocessaffinitymask (handle hprocess, dword_ptr dwprocessaffinitymask );

The first parameter is used to specify which process to pass in its handle. The second process is used to specify the CPU core to execute the process.

Dword_ptr is actually unsigned long *. unsigned long type for pointer precision. use when casting a pointer to a long type to perform pointer arithmetic. (also commonly used for general 32-bit parameters that have been extended to 64 bits in 64-bit windows .)

DWORD is actually unsigned long. In Windows, it is often used to save addresses or store pointers.

For example, call a function as follows:

: Setprocessaffinitymask (: getcurrentprocess (), 0x1); you can specify that the currently executed process runs on the first CPU (00000001 ). For dual-core CPUs,

: Setprocessaffinitymask (: getcurrentprocess (), 0x2); can be specified to run on the second CPU. (00000010)

: Setprocessaffinitymask (: getcurrentprocess (), 0x3); can be run on any two CPUs. (000000011)

: Setprocessaffinitymask (: getcurrentprocess (), 0x3); can run on the third CPU. (000000100)

: Setprocessaffinitymask (: getcurrentprocess (), 0x3); can run on the first and third CPUs. (00000101)

 

And so on...

 

 

HandleGetCurrentProcess(Void );

You can obtain the handle of the current process. Note that this handle is a pseudo handle. It can only represent the handle of the current process in our process. In fact, this function only returns the-1 value. That is to say, in our program,-1 can represent the handle of this process.

(2) The program code is:

 

 

# Include <Windows. h> <br/> # include <stdlib. h> <br/> # include <tchar. h> <br/> int _ tmain (int argc, _ TCHAR * argv []) <br/>{< br/> int busyTime = 10; <br/> int idleTime = busyTime * 5; <br/>__ int64 startTime = 0; <br/>: SetThreadAffinityMask (: GetCurrentProcess (), 0x00000001 ); <br/> while (true) <br/>{< br/> startTime = GetTickCount (); <br/> // busy loop <br/> while (GetTickCount ()-startTime) <= busyTime ); <br/> // idle loop <br/> Sleep (idleTime); <br/>}< br/> return 0; <br/>}

Gettickcount () can be used to obtain the millisecond value of the system's time from startup to running. Up to 49.7 days can be counted. We use it to determine how long the busy loop will last.

Idletime is five times of busytime. You can modify the idletime value to bring it closer to 50%. Different machines are different.

_ Int64 is a 64-bit extension of VC ++. The value range is [-2 ^ 63,2 ^ 63 ). When the 64-bit and 32-bit values are mixed, a 32-bit integer is implicitly converted to a 64-bit integer. When you input and output the data, using cin and cout may cause errors. Use scanf ("% I64d", & a); and printf ("% I64d", );

There is also unsigned _ int64, and its range is [0, 2 ^ 64 ).

The 64-bit extension in g ++ is long and unsigned long. The range is similar to the operation. The input and output use scanf ("% lld", & a); and printf ("% lld", );

 

Int _ tmain (int argc, _ TCHAR * argv []).

The _ tmain symbol is usually found in the console project created by VC ++. It is added to ensure unicode porting (generally _ t, _ T, T () these are related to unicode ). It is defined in the header file tchar. h.

(3) Draw a sine curve:

 

# Include <windows. h> <br/> # include <stdlib. h> <br/> # include <math. h> <br/> # include <tchar. h> <br/> const Double Split = 0.01; <br/> const int COUNT = 200; <br/> const double Pi = 3.14159265; <br/> const int interval = 300; <br/> int _ tmain (INT argc, _ tchar * argv []) <br/>{< br/> DWORD busyspan [count]; // array of busy times <br/> DWORD idlespan [count]; // array of idle times <br/> int half = interval/2; <br/> do Uble radian = 0.0; <br/> // how can I approximate a sine curve? This way! <Br/> for (INT I = 0; I <count; ++ I) <br/>{< br/> busyspan [I] = (DWORD) (Half + (sin (pI * radian) * Half); <br/> idlespan [I] = interval-busyspan [I]; <br/> radian + = split; <br/>}< br/> DWORD starttime = 0; <br/> Int J = 0; <br/>: setprocessaffinitymask (: getcurrentprocess (), 0x00000002); <br/> while (true) <br/>{< br/> J = J % count; <br/> starttime = gettickcount (); <br/> while (gettickcount ()-starttime) <= busyspan [J]); <br/> sleep (idlespan [J]); <br/> J ++; <br/>}< br/> return 0; <br/>}

The half + (sin (pI * radian) * Half) value of each interval is saved to busyspan [I] by dividing 200 portions in 2 * pI of a cycle. store it in idlespan [I]. Half is half of the value range interval. In this way, we can approximate a sine curve.

Running effect:

(4) You can use the rdtsc command to obtain the number of running cycles of the current CPU core.

Define functions on the x86 Platform:

Inline _ int64 GetCPUTickCount () <br/>{< br/>__ asm <br/>{< br/> rdtsc; <br/>}< br/>}

On the x64 platform, define:

# Define GetCPUTickCount () _ rdtsc ()

Use the callntpowerinformation API to obtain the CPU frequency and convert the number of cycles to milliseconds. For example:

_ PROCESSOR_POWER_INFORMATION info; <br/> CallNTPowerInformation (11, // query processor power information <br/> NULL, // no input buffer <br/> 0, // input buffer size is zero <br/> & info, // output buffer <br/> sizeof (info) // outbuf size <br/> ); <br/>__ int64 t_begin = GetCPUTickCount (); <br/> // do something <br/>__ int64 t_end = GetCPUTickCount (); <br/> millisec = (double) t_end-(double) t_begin)/(double) info. currentMhz; 

 

The rdtsc command reads the number of cycles of the current CPU. in multiple CPU Systems, the number of cycles varies with the CPU base and frequency. It is meaningless to calculate the number of cycles obtained from two different CPUs. Therefore, you need to use setprocessaffinitymask to avoid Process Migration. In addition, the CPU frequency also varies with the system power supply and load.
More:

In Linux, such as the system monitor in Ubuntu, how does one draw a sine curve? Listen to the next decomposition.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.