Board logo

Subject: 微软面试题,如何控制CPU占用率? [Print This Page]

Author: Passion    Time: 2007-7-24 10:01     Subject: 微软面试题,如何控制CPU占用率?

假使Windows中其他进程都不怎么占CPU,如何写一个程序,让CPU占用率保持在50%左右。
或者更复杂一点,如何定量控制CPU占用率。

附件里头一个图,是程序控制的显示正弦波的占用率曲线。

Image Attachment: [一个让] 4caedc7a020011qx.jpg (2007-7-24 10:01, 43.27 K) / Download count 463
http://bbs.cnpack.org/attachment.php?aid=335


Author: shenloqi    Time: 2007-7-24 16:01

...一个不是方法的方法,在任务管理器的CPU占用的图上自己画图...
Author: Passion    Time: 2007-7-24 20:09

楼上的沈算你狠。
Author: Passion    Time: 2007-7-25 09:24

转贴stanleyxu在QQ群里头的思路。

stanleyxu(*)(38656530) 09:07:29
其实就是创建线程
双核就创建2个
然后呢,我规定,比如100毫秒内,20毫秒是sleep,80毫秒是processmessage
这样cpu占用大致保持在80
先通过这个思路实现一个线程,控制cpu占用,cpu值是个属性
然后你就可以写个什么sin函数,控制曲线,包括振幅,速度

program Project1;

{$APPTYPE CONSOLE}

uses
  Classes, SysUtils, Windows;

procedure ProcessMessages;
var
  MsgRec : TMsg;
begin
  while PeekMessage(MsgRec, 0 {FWindowHandle}, 0, 0, PM_REMOVE) do begin
     TranslateMessage(MsgRec);
     DispatchMessage(MsgRec)
  end;
end;

procedure Delay(MilliSecs: DWORD);
var
  T: DWORD;
begin
  T := GetTickCount;
  while GetTickCount - T < MilliSecs do
  begin
    // Any more precisely way?
    ProcessMessages;
  end;
end;

function GetNumberOfProcessors: Integer;
var
  SI: TSystemInfo;
begin
  GetSystemInfo(SI);
  Result := SI.dwNumberOfProcessors;
end;

type
  TCPUConsumerThread = class(TThread)
  public
    nRound: Extended;
    ExpectedCPUusage: Integer;
    function GetSleepDuration: DWORD;
    procedure Execute; override;
  end;

const
  DelayDuration = 56;
  TaskManRefreshRate = 100; //not less than 56 ms
var
  Working: Boolean;

function TCPUConsumerThread.GetSleepDuration: DWORD;
const
  Delta = Pi / 80;
begin
  ExpectedCPUusage := Round((Sin(nRound / 4) + 2){1-3} * 10);
  nRound := nRound + Delta;

  Result := TaskManRefreshRate * (100 - ExpectedCPUusage) div 100;
end;

procedure TCPUConsumerThread.Execute;
var
  SleepDurationOfThisRound: DWORD;
  I: Integer;
begin
  while Working do
  begin
    SleepDurationOfThisRound := GetSleepDuration;
    if TaskManRefreshRate > SleepDurationOfThisRound then
      Delay(TaskManRefreshRate - SleepDurationOfThisRound);
    if SleepDurationOfThisRound > 0 then
      Sleep(SleepDurationOfThisRound);
  end;
end;

var
  ACPUConsumerThread: TCPUConsumerThread;
  I: Integer;

begin
  Working := True;
  for I := 1 to GetNumberOfProcessors do
    with TCPUConsumerThread.Create(True) do
    begin
      FreeOnTerminate := True;
      ExpectedCPUusage := 20;
      Resume;
    end;

  WriteLn('Running... (press any key to abort)');
  ReadLn;
  Working := False;
  WriteLn('press any key to exit');
  ReadLn;
end.

stanleyxu(*)(38656530) 09:10:53
我的思路大致这样,现在振幅不高兴仔细研究了。谁有兴趣谁去继续研究
要让cpu占用到100,我用delay函数,具体实现还可以改,可能可以直接用什么cpu指令,强制占用cpu之类的?
因为delay里面用到GetTickCount,而这个函数的精度最低就是56毫秒,所以我硬性规定,每次占用cpu至少56毫秒。
因为时间再短,可能就误差很厉害了。
Author: stanleyxu2005    Time: 2007-7-25 09:40

我说的办法效果一般,只能粗略模拟顶楼效果。

[ 本帖最后由 stanleyxu2005 于 2007-7-25 09:44 编辑 ]

Image Attachment: [效果图] {60BFBE90-AD59-4E69-94A0-96D9BFF97C60}.JPG (2007-7-25 09:44, 82.71 K) / Download count 433
http://bbs.cnpack.org/attachment.php?aid=336


Author: jAmEs_    Time: 2007-7-25 11:24



QUOTE:
原帖由 shenloqi 于 2007-7-24 16:01 发表
...一个不是方法的方法,在任务管理器的CPU占用的图上自己画图...

兄弟太有才了
Author: Passion    Time: 2007-7-25 17:10

转贴群里shenloqi的不bt的看法:

要占用CPU到指定的利用率,真正处理应该不会很容易,起码会遇到多核心和其他程序干扰的问题,只有在环境理想的情况下才可能通过程序控制,通过程序控制的最简单的方法就是分时间片的方法,先设定程序的优先级和CPU的相关性(SetProcessAffinityMask),如果有多个CPU则需要有多个线程,同时设置线程的相关性(SetThreadAffinityMask),然后把取CPU利用率的时间间隔细分,然后循环占用时间片。
Author: kendling    Time: 2007-7-27 13:40

这个问题有点挑战性。。。
Author: zzzl    Time: 2007-8-2 08:42

晕,参考开源软件boinc,精确控制cpu占用率
Author: zzzl    Time: 2007-8-2 22:15

。。。
谁能开发一个基于那个图的游戏
Author: Rainstorey    Time: 2007-8-3 11:04

硬盘内存读写有DMA,图形处理有GPU,所以最耗费CPU时间的应该是数值计算.这就是用算法能解决该问题的最佳方法.找出一算法来无限逼近正弦图形应该就可以了.当然运行前先设置主线程的优先级为实时来更好的控制CPU的时间片.




Welcome to CnPack Forum (http://bbs.cnpack.org/) Powered by Discuz! 5.0.0