用您喜欢的语言编写代码,让 Windows 任务管理器在 CPU 使用历史记录中显示正弦波。
这是来自微软中国的技术面试测验。我认为这是一个很好的问题。尤其值得了解候选人如何理解和找出解决方案。
编辑:如果可能涉及多核(cpu)情况,这是一个很好的观点。
用您喜欢的语言编写代码,让 Windows 任务管理器在 CPU 使用历史记录中显示正弦波。
这是来自微软中国的技术面试测验。我认为这是一个很好的问题。尤其值得了解候选人如何理解和找出解决方案。
编辑:如果可能涉及多核(cpu)情况,这是一个很好的观点。
Windows 中的线程时间片是 40 毫秒,iirc,因此这可能是用作 100% 标记的好数字。
unsigned const TIME_SLICE = 40;
float const PI = 3.14159265358979323846f;
while(true)
{
for(unsigned x=0; x!=360; ++x)
{
float t = sin(static_cast<float>(x)/180*PI)*0.5f + 0.5f;
DWORD busy_time = static_cast<DWORD>(t*TIME_SLICE);
DWORD wait_start = GetTickCount();
while(GetTickCount() - wait_start < busy_time)
{
}
Sleep(TIME_SLICE - busy_time);
}
}
这将给出大约 14 秒的时间。显然,这是假设系统中没有其他重要的 cpu 使用率,并且您仅在单个 CPU 上运行它。这些在现实中都不是很常见。
这是在 Python 中稍作修改的@flodin 解决方案:
#!/usr/bin/env python
import itertools, math, time, sys
time_period = float(sys.argv[1]) if len(sys.argv) > 1 else 30 # seconds
time_slice = float(sys.argv[2]) if len(sys.argv) > 2 else 0.04 # seconds
N = int(time_period / time_slice)
for i in itertools.cycle(range(N)):
busy_time = time_slice / 2 * (math.sin(2*math.pi*i/N) + 1)
t = time.perf_counter() + busy_time
while t > time.perf_counter():
pass
time.sleep(time_slice - busy_time);
time_period
可以使用和time_slice
参数微调 CPU 曲线。
好的,我有一个不同的,可能比我的第一个答案更好的解决方案。
与其尝试操纵 CPU,不如挂钩到任务管理器应用程序,强制它绘制您想要的内容,而不是 CPU 结果。接管绘制图形的 GDI 对象等。有点“作弊”,但他们没有说你必须操纵 CPU
或者甚至挂钩从任务管理器获取 CPU % 的调用,而是返回正弦结果。
今天的 PC 运行了数百(数千?)个线程,我认为甚至接近的唯一方法是尽可能快地轮询 CPU 使用率,并且如果使用百分比低于曲线上的应有位置, 启动一个只搅动数字的简短方法。这至少会在需要的地方带来典型的低使用率,但我想不出一个好的方法来降低它,而不以某种方式控制其他线程,并做一些事情,比如强制降低他们的优先级。
像这样的东西:
while(true)
{
for(int i=0;i<360;i++)
{
// some code to convert i into radians if needed
...
Thread.Sleep(Math.Sin(i)*something_that_makes_it_noticeable_number_of_ms+something_that_makes_it_non_negative)
// some work to make cpu busy, may be increased to bigger number to see the influence on the cpu.
for(j=0;j<100;j++);
}
}