10

100 スレッドを作成する Win32 アプリケーション (TThread クラスを使用する 32 ビットの Delphi-7) を作成しました。各スレッドは、再開されると、スレッド オブジェクトに関連付けられた 64 ビット カウンターを (ループ内で) 継続的にインクリメントします (データのロックや共有はありません)。

システムを 10 ~ 15 秒間実行し、その後停止すると、各スレッドでほぼ同じカウントが表示されるはずです。しかし、私が観察したところ、81 のスレッドが 4 億回未満のループで実行され、残りのスレッドは 9 億 5000 万回以上ループしました。最速の 21 億 1100 万に比べて、最も遅いスレッドは 2 億 3000 万しかありませんでした。

MSDN によると、プリエンプティブ マルチタスキングは (プロセス レベルではなく) スレッド レベルであるため、各スレッドはラウンド ロビン方式でタイム スライスを取得する必要があります。ここで何が欠けているのですか?この不一致はなぜですか?

Edit1: マシン構成: Intel i7 クアッド コア 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 の時代には、さまざまな VM に均等な時間を与えることができる非常に優れたスケジューラでした。しかし、Dave Cutler のグループによって開始された NT ブランチでは、スケジューリングは純粋に優先度に基づいています。

優先順位が最も高いスレッドが CPU を取得します。Windows には、スレッドの優先度をいじくり回して、スレッドが作成されたときに取得したデフォルトの優先度から変更するコードの別のチャンクがあります。そのコードは、フォアグラウンドにあるウィンドウを所有するスレッドのようなものを認識しています。または、通知された同期オブジェクトを待機しているスレッド。または、優先順位の逆転の問題を解決しようとする、より奇妙なスケジューリングの問題。順番が回っていなくても、ランダムに実行する機会をスレッドに与える。

最初にまともなコードを書くことに集中してください。100 のスレッドを開始することは、非常に正気なことではありません。マシンが実際に利用できないリソースを消費しようとしています。誰も100コアのマシンを持っていません。まだ。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を使用)。2番目のケースでは、値は互いにはるかに近かった。

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

ハイパースレッディングシステムで実行すると、一部のスレッドが「不運」になる可能性があることを理解できます。同じ物理プロセッサ上の他のスレッドと競合するようにスケジュールされており、この仮想コアへの「ソフトアフィニティ」のために実行されます。その上で何度も何度も、したがって他よりも低いスコア。

しかし、各スレッドを固定コアにバインドすることが非ハイパースレッドシステムで役立つ理由については、私にはわかりません。

他のプロセスによるコアでのアクティビティなど、おそらく他のランダムなものが関係しています。同じコアに関連付けられている他のプロセスのスレッドが突然ウェイクアップし、(比較的)重い作業を開始した場合、スレッドは「不運」になる可能性があります。

しかし、これはすべて推測です。

于 2012-08-23T14:02:18.090 に答える
1

Windows 7 はユーザーランド向けに設計されています。最初のスレッドが作業を行いたい場合、OS はそれにタイム スライスを与えます。ユーザーであるあなたは、結局のところ、それを開始したばかりです。連続する 50 番目のスレッド (同じプロセスから!) が作業を行うまでに、より優先度の高いスレッド (Windows 7 自体によって制御されるバックグラウンド プロセス) が介入ます

あなたも私も、ユーザー ランド プロセスの気まぐれに基づいて CPU 時間を分配する個人用の OS は本当に必要としません。2008 R2 サーバーがこれをどのように処理したかを知りたいです。また、[Advanced] タブの設定で「プロセッサ リソースの割り当て方法を選択してください」という設定を試してみることもできます。

于 2012-08-14T11:36:42.473 に答える
-1

ここにはいくつかの正当な理由があります..しかし、考慮すべき機能がいくつかあります. Windows は、ソフトウェアでマルチタスクを実行しようとしています。ハードウェアはマルチタスキングではなく、並列処理システムが行うことを実行するためにパワーを使用します。窓下は優先。多くの点で..そしてその混乱。

このように説明させてください。コアの使用を監視する小さなプログラムがあります。Windows がロードされると、すべてのコアが使用されると考えるでしょう。いいえ。Windows がロードされると、他のコアが使用され始めます。次に、Windowsがロードされると、コアにアクセスできるため、ロードが加速すると考えるでしょう。加速しません。ロードを高速化するためにフルスピードのコアを使用しません。プログラムがロードおよび実行されているときに、Windowsがプログラムを1つのコアごとに押し込んだとしても、プログラムが終了するのを待ちます。すべてのコアを使用して各プログラムを処理した場合、ソフトウェア (ハードウェアよりも約 100 倍遅い) を使用して、もう一方の端で部品を組み立てます。ずっと前に、Intel はハードウェアを並列処理に変更したいと考えていましたが、MS はソフトウェアがそのように設計されていないため「いいえ」と言いました。現在、彼らはシリアル ベースのハードウェア設計を N ポイントに押し込もうとしています。MS が NT ソフトウェアを購入した後でさえも。最近、彼らはそのデザインの多くを使用することを忘れています. いくつかのハードウェアの変更が必要です。プログラミング言語の変更 (MS がプログラミング言語を作成) が必要であり、Windows のコアを再設計する必要があります。変更されていません。戻って最初からやり直す必要があります。頑張ってください。この考えがどれほど古いかを教えてください... VIVA La' Amiga。

于 2013-06-27T15:22:29.333 に答える