Two years ago, Microsoft's Asian Research Institute published the book "The beauty of programming". Chapter 1 section Section 1 "let you know the CPU usage curve, it can be said that it has set off a game-to-CPU usage curve nationwide. I am even thinking about how to handle the CPU usage curve while taking the bus.
The book provides such a refreshing figure, attracting thousands of IT teenagers:
You may think this is not fun enough. Me too. By the way, we plan to discuss with you the effect of the figure below-dual-core CPU, circle on the left and draw on the right hand!
When the book was published, I was working as an intern in the innovation engineering group of Microsoft Asia Research Institute. Several authors of the book were my good friends, such as Li Dong and Chen Yuan. So I can tell you responsibly, all interns in this book were using Intel P4 GHz Single-core CPU! O (partition _ partition) o
Today, I suddenly thought about it. I plan to use my Thinkpad T60. The CPU is Genuine Intel (R) CPU T2400 @ 1.83 Ghz, dual-core.
First, I will translate the C ++ Code provided in the book into C #. The translation process is not technically difficult. It is only for you to know about it:
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace ConsoleApplication1{ class Program { static void Main(string[] args) { const double SPLIT = 0.01; const int COUNT = 200; const double PI = 3.14159265; const int INTERVAL = 100; double[] busySpan = new double[COUNT]; //array of busy times double[] idleSpan = new double[COUNT]; //array of idle times int half = INTERVAL / 2; double radian = 0.0; for (int i = 0; i < COUNT; i++) { busySpan[i] = (double)(half + (Math.Sin(PI * radian) * half)); idleSpan[i] = INTERVAL - busySpan[i]; radian += SPLIT; } double startTime = 0; int j = 0; while (true) { j = j % COUNT; startTime = Environment.TickCount; while ((Environment.TickCount - startTime) <= busySpan[j]) ; System.Threading.Thread.Sleep((int)idleSpan[j]); j++; } } }}
Run the code f5. the running result is as follows:
Sure enough, like everyone expected, both CPUs show very distorted and irregular sine curves.
According to the book, the C ++ program can use the SetThreadAffinityMast () function in WinAPI to fix the program to a specific CPU for execution.
I checked MSDN. Of course, there are similar Manage codes in. NET. See http://msdn.microsoft.com/zh-tw/library/system.diagnostics.process.processoraffinity (VS.80). aspx
According to MSDN, a simple sentence is added to the Code:
System.Diagnostics.Process p = System.Diagnostics.Process.GetCurrentProcess(); p.ProcessorAffinity = (IntPtr)0x0001;
Then press F5 again, as shown in the curve in the CPU:
The sine curve of the Number 1 CPU rule is quite perfect, and the number 2 CPU usage is always 0.
It seems that this is what we want to achieve in the book.
This effect is boring. No. 2 CPU resources are wasted. Is there any way to use it?
Let's analyze the two codes:
While (Environment. TickCount-startTime) <= busySpan [j]);
System. Threading. Thread. Sleep (int) idleSpan [j]);
It means that during the specified time interval (100 milliseconds in the Program), full load is run (through an empty loop) the running time required to construct the sine function (obtained from the previous calculation), and the rest of the time goes to bed. For example, if you run 69 ms and sleep for 31 ms, the average CPU usage is 100 during this 69% Ms period. Since the CPU usage curve is updated once every second, the program uses an average node every 100 milliseconds, and the curve is smooth enough.
Continue divergence. In the preceding example, if the task is running for 69 ms, what about sleeping for 50 ms? The CPU usage for the current 100 ms is still 69%, but if the algorithm is not adjusted, the CPU usage for the next 100 ms is still an average node, which affects the CPU usage for the next 100 ms. The curve of the previous one is totally wrong, just like Domino.
That is to say, the time period we use to control the average CPU usage, each segment must be equal.
We have considered that the above Code runs for 69 milliseconds in the No. 1 CPU, and the remaining 31 milliseconds. If it is transferred to the No. 2 CPU, the CPU usage on the No. 1 will be reduced to 0, but at the same time, we can "draw a party" in CPU 2.
To sum up, when the Number 1 CPU usage is small, the program "draws" in the Number 2 CPU; when the number 1 CPU usage ends, the "party" of the current cycle in CPU 2 must be completed.
It should be noted that if a good CPU has been set to 69 milliseconds, the number of CPUs on the 2 must be set to 31 milliseconds.
Based on this idea, we will first try a simple experiment: Draw a cosine curve in the rest period after the sine curve in CPU 1, and draw a cosine curve in CPU 2. Have you forgotten the trigonometric function you learned in junior high school?
We changed the empty loop in the original code:
while (true) { j = j % COUNT; p.ProcessorAffinity = (IntPtr)0x0001; startTime = Environment.TickCount; while ((Environment.TickCount - startTime) <= busySpan[j]) ; p.ProcessorAffinity = (IntPtr)0x0002; while ((Environment.TickCount - startTime) <= idleSpan[j]) ; j++; }
The result of "left-hand sine and right-hand cosine" is unsatisfactory:
We noticed that this curve is not as accurate as when a single CPU was running.
The reason is that the CPU switching operation takes up time. For example, if the sine was previously set to 69 ms, we calculated that the cosine should be set to 31 ms, but the CPU switching operation may take 3 ms (or more, or each time it takes a different time ), the overall interval is no longer within 100 milliseconds, so there is an error in the curve results.
At this point, my ideas have been completed and I believe everyone understands.
However, we have encountered some obstacles to pursue perfection.
After some fine-tuning on the cycle and changing the cosine function to a simple square wave function, the final result is as shown at the beginning of this article.
Adjustment methods? Sorry, I have not yet come up with a method that can convince everyone to make adjustments in a formula. You can see the audience here and see how they are doing ~