10

我编写了一个 Win32 应用程序(在 Delphi-7 中,它是 32 位使用 TThread 类)来创建 100 个线程。每个线程在恢复时将连续(在循环中)增加与线程对象关联的 64 位计数器(因此不会锁定或共享数据)。

如果您让系统运行 10 到 15 秒然后停止,您应该会看到每个线程中的计数大致相同。但我观察到,81 个线程运行了 4 亿次以下的循环,其余的循环超过了 9.5 亿次。与最快的 21.11 亿相比,最慢的线程只有 2.3 亿。

根据 MSDN,抢占式多任务处理处于线程级别(而不是进程级别),因此我的每个线程都应该以循环方式获得其时间片。我在这里缺少什么,为什么会出现这种差异?

Edit1:机器配置:Intel i7 Quad Core 3.4GHz,超线程开启(一次 8 个活动线程)。运行 Windows-7 64 位专业版(并且测试应用程序是 32 位)

Edit2(线程代码):测试应用程序是在启用优化且没有任何调试信息的情况下构建的。在 IDE 之外运行测试应用程序。

type

  TMyThread = class(TThread)
  protected
    FCount: Int64;
  public
    constructor Create;
    procedure Execute; override;
    property Count: Int64 read FCount;
  end;


{ TMyThread }

constructor TMyThread.Create;
begin
  inherited Create(True);
  FCount := 0;
end;  

procedure TMyThread.Execute;
begin
  inherited;
  while not Terminated do
  begin
    Inc(FCount);
  end;
end;
4

4 回答 4

10

对于内核来说,循环调度是一种显而易见的策略。然而,这不是 Windows 调度程序的工作方式。在 Windows 9x 时代,它曾经是一个非常有能力为各种虚拟机提供同等时间的调度程序。但不是在由 Dave Cutler 小组启动的 NT 分支中,调度纯粹基于优先级

无论哪个线程具有最高优先级,都会获得 CPU。Windows 中有另一段代码修改线程的优先级,从创建线程时获得的默认优先级修改它。该代码知道诸如拥有前台窗口的线程之类的东西。或者一个线程正在等待收到信号的同步对象。或者尝试解决优先级反转问题的更奇怪的调度问题。随机给一个线程一个运行的机会,即使它不是轮到它。

首先专注于编写健全的代码。启动一百个线程并不是一件很明智的事情。您正在尝试消耗机器实际上没有可用的资源,没有人拥有具有一百个核心的机器。然而。2 的幂,首先获得一台 128 核的机器。

于 2012-08-13T22:14:09.030 回答
3

我已经复制并确认了您的结果。此外,禁用线程优先级提升不会改变分布。GetThreadTimes报告具有较高 Values 的线程占用了更多 UserTime,反之亦然,而 KernelTime 似乎与 Values 没有相关性。

Thread 97: 1081,5928 Ke:0 Us:25116161
Thread 98: 1153,8029 Ke:0 Us:26988173
Thread 99: 704,6996  Ke:0 Us:16848108

显然,有些线程确实比其他线程运行得更频繁。

我没有绘制结果图,但我想我们看到的是正态分布,这意味着结果取决于许多因素,其中一些是随机的。

我尝试禁用超线程(这有点平滑结果),然后为每个线程分配一个物理处理器(通过使用SetThreadAffinityMask)。在第二种情况下,价值观彼此更接近。

SetThreadAffinityMask(Self.Handle, 1 shl (FIndex mod 4));

我可以理解在超线程系统上运行如何使某些线程“不走运”:它们被安排与同一物理处理器上的其他线程竞争,并且由于对这个虚拟内核的“软亲和力”它们可以运行一次又一次,因此得分低于其他人。

但至于为什么将每个线程绑定到一个固定内核有助于非超线程系统,我不知道。

可能还涉及其他随机事物,例如其他进程在内核上的活动。如果与同一核心关联的其他进程的线程突然唤醒并开始做一些(相对)繁重的工作,线程可能会“不走运”。

不过,这一切都是猜测。

于 2012-08-23T14:02:18.090 回答
1

Windows 7 专为用户领域而设计。当你的第一个线程想要工作时,操作系统会给它一个时间片。毕竟,您,用户,才刚刚开始。当连续第 50 个线程(来自同一个进程!)想要工作时,更高优先级的线程(由 Windows 7 本身控制的后台进程)介入。这种情况发生的方式使得一些线程更幸运

你和我真的不想要一个根据用户登陆进程的突发奇想来分配 CPU 时间的个人操作系统。我很想知道 2008 R2 服务器是如何处理这个问题的。您还可以使用“高级”选项卡设置:“选择如何分配处理器资源”。

于 2012-08-14T11:36:42.473 回答
-1

这里有一些很好的推理..但是有一些功能需要考虑。Windows 正在尝试使用软件进行多任务处理。你的硬件不是多任务处理,它使用能力来做并行处理系统会做的事情。在windows下,它优先。在很多方面......而且它令人困惑。

让我这样解释。我有一个小程序可以监视我的核心以供使用。当 Windows 加载时,您会认为所有内核都会被使用。不。随着 Windows 的加载,其他内核开始使用。然后你会想,当 Windows 加载时,它会加速加载,因为它可以访问内核。它不会加速。它不使用核心是全速加载更快。即使 Windows 在加载和运行时将程序推向 1 个核心,它也会等待它们完成。如果它使用所有内核来处理每个程序,它使用软件(大约比硬件慢 100 倍)来组装另一端的部件。很久以前,英特尔想将硬件更改为并行处理,MS 说“不”,因为他们的软件不是为它设计的。现在他们正试图将基于串行的硬件设计推向 N 点。甚至在 MS 买了 NT 软件之后。最近,他们忘记了使用它的大部分设计。需要进行一些硬件更改。需要编程语言更改(MS创建了编程语言)并且需要重新设计windows的核心。没有改变。它需要返回并从头开始。祝你好运。告诉你这个想法有多古老...... VIVA La' Amiga。

于 2013-06-27T15:22:29.333 回答