Skip to content

CPU占用率形成正弦曲线(C#)

这是《编程之美——微软技术面试心得》里的第一个题,后来我推荐到微软亚洲研究院的一个实习生面试的时候做的正是这个题。 其实这个题难度适中,现在机器都是多核CPU,照书里的答案去做早就不行了。 下面我给出一个适用于双核CPU上在两个核都形成正弦曲线的做法吧。

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading;

namespace CPU { public class Sin1ThreadParam { public int AffinityMask = 0x00000000;

    public Sin1ThreadParam(int AffinityMask)
    {
        this.AffinityMask = AffinityMask;
    }
}

class Sin1
{
    public void DoWork(object o)
    {
        Sin1ThreadParam param = o as Sin1ThreadParam;
        if (param != null)
        {
            // 设置线程CPU亲和性
            IntPtr nHD = new IntPtr(Thread.CurrentThread.ManagedThreadId);
            Win32.SetThreadAffinityMask(nHD, param.AffinityMask);

            // 采样率
            const double SPLIT = 0.01;
            // 采样总数
            const int COUNT = 200;
            const double PI = 3.14159265;
            // 扫描速度,控制曲线波长
            const int INTERVAL = 300;

            // 忙循环时间长度
            int[] busySpan = new int;
            // 闲循环时间长度
            int[] idleSpan = new int;
            int half = INTERVAL / 2;
            // X
            double radian = 0.0;

            // 构成一个具有COUNT个采样点的忙、闲循环
            for (int i = 0; i < COUNT; i++)
            {
                busySpan = (int)((half + (Math.Sin(PI * radian) * half)));
                idleSpan = INTERVAL - busySpan;
                radian += SPLIT;
            }

            int startTime = 0;
            int j = 0;

            // 按照忙闲循环比率跑死循环和Sleep
            while (true)
            {
                j = j % COUNT;
                startTime = Environment.TickCount;
                while ((Environment.TickCount - startTime) <= busySpan)
                {

                }
                Thread.Sleep(idleSpan);
                j++;
            }
        }
    }
}

}

调用的时候用两个线程去跑,分别用Windows API的SetThreadAffinityMask指定不同的CPU亲和性。

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Diagnostics; using System.Runtime.InteropServices;

namespace CPU { class Win32 {

    public static extern int SetThreadAffinityMask(IntPtr hWnd, int nIndex);
}

class Program
{
    static void Main(string[] args)
    {
        Sin1 sin11 = new Sin1();
        Thread t1 = new Thread(new ParameterizedThreadStart(sin11.DoWork));
        Sin1ThreadParam p1 = new Sin1ThreadParam(0);
        Thread t2 = new Thread(new ParameterizedThreadStart(sin11.DoWork));
        Sin1ThreadParam p2 = new Sin1ThreadParam(1);

        t1.Start(p1);
        t2.Start(p2);
    }
}

}

结果是这样子的: