181

マルチコア コンピューターのポイントは、複数のスレッドを同時に実行できることだと思いました。その場合、クアッドコア マシンを使用している場合、一度に 4 つ以上のスレッドを実行する意味はありますか? お互いに時間 (CPU リソース) を盗んでいるだけではないでしょうか?

4

17 に答える 17

108

その答えは、並列処理であるスレッドの目的を中心に展開しています。つまり、複数の個別の実行行を一度に実行することです。「理想的な」システムでは、コアごとに 1 つのスレッドが実行され、中断はありません。実際にはそうではありません。4 つのコアと 4 つの作業スレッドがある場合でも、プロセスとそのスレッドは常に他のプロセスとスレッドに切り替えられます。最新の OS を実行している場合、すべてのプロセスに少なくとも 1 つのスレッドがあり、多くのプロセスにはそれ以上のスレッドがあります。これらのプロセスはすべて同時に実行されます。おそらく数百のスレッドがすべてマシン上で実行されているでしょう。スレッドから時間が「盗まれる」ことなくスレッドが実行される状況は決してありません。(まあ、リアルタイムで実行されている場合はそうかもしれません、リアルタイム OS を使用している場合、または Windows でもリアルタイム スレッド優先度を使用している場合。しかし、それはまれです。)

その背景として、答え: はい、真の 4 コア マシンで 4 つ以上のスレッドを使用すると、「互いに時間を盗む」状況が発生する可能性がありますが、個々のスレッドが 100% CPU を必要とする場合のみです。スレッドが 100% 動作していない場合 (UI スレッドが動作していない可能性があるため、またはスレッドが少量の作業を行っているか他の何かを待機している場合)、別のスレッドがスケジュールされているのは実際には良い状況です。

実際にはそれよりも複雑です:

  • すべてを一度に行う必要がある 5 つの作業がある場合はどうすればよいでしょうか? 4 つ実行してから 5 つ目を後で実行するよりも、すべてを一度に実行する方が理にかなっています。

  • スレッドが本当に 100% の CPU を必要とすることはまれです。たとえば、ディスクやネットワーク I/O を使用する瞬間、何の役にも立たない待機に時間を費やしている可能性があります。これは非常に一般的な状況です。

  • 実行する必要がある作業がある場合、1 つの一般的なメカニズムは、スレッドプールを使用することです。コアと同じ数のスレッドを持つことは理にかなっているように思えるかもしれませんが、.Net スレッドプールには、プロセッサごとに最大 250 のスレッドを使用できます。彼らがこれを行う理由は定かではありませんが、私の推測では、スレッドで実行するために与えられたタスクのサイズに関係しています。

つまり、時間を盗むことは悪いことではありません (また、盗むということでもありません。それは、システムがどのように機能するかということです。) スレッドが実行する作業の種類に基づいて、マルチスレッド プログラムを作成します。これは CPU ではない可能性があります。 -バウンド。プロファイリングと測定に基づいて、必要なスレッドの数を計算します。スレッドではなく、タスクまたはジョブの観点から考えた方が便利な場合があります。作業オブジェクトを作成し、それらを実行するプールに渡します。最後に、あなたのプログラムが本当にパフォーマンスが重要でない限り、あまり心配しないでください :)

于 2010-06-27T04:37:23.840 に答える
54

スレッドが存在するからといって、常にアクティブに実行されているとは限りません。スレッドの多くのアプリケーションでは、スレッドの一部が何かを実行する時間になるまでスリープ状態になります。たとえば、ユーザー入力によってスレッドが起動し、何らかの処理が行われ、スリープ状態に戻るなどです。

基本的に、スレッドは、別のタスクの進行状況を認識する必要がなく、互いに独立して動作できる個々のタスクです。同時に実行する能力よりも多くのこれらを持っている可能性は十分にあります。時々列に並んで待たなければならない場合でも、利便性のために役立ちます。

于 2010-06-27T02:25:59.397 に答える
28

要点は、スレッド数がコア数を超えたときに実際のスピードアップが得られないにもかかわらず、スレッドを使用して、相互依存する必要のないロジックの断片を解きほぐすことができるということです。

適度に複雑なアプリケーションでも、単一のスレッドを使用してすべてをすばやく実行しようとすると、コードの「フロー」のハッシュが作成されます。単一のスレッドは、これをポーリングし、それをチェックし、必要に応じて条件付きでルーチンを呼び出すことにほとんどの時間を費やします。

これを、スレッドをタスク専用にすることができる場合と比較して、個々のスレッドを見ると、そのスレッドが何をしているかを確認できます。たとえば、1 つのスレッドがソケットからの入力の待機をブロックし、ストリームをメッセージに解析し、メッセージをフィルター処理し、有効なメッセージが届いたら、それを他のワーカー スレッドに渡します。ワーカー スレッドは、他の多くのソースからの入力を処理できます。これらのそれぞれのコードは、他に行うべきことがないことを明示的にチェックする必要なく、クリーンで意図的なフローを示します。

このように作業を分割することで、アプリケーションはオペレーティング システムに依存して CPU で次に何をするかをスケジュールできるため、何がブロックされ、何が処理の準備ができているかについて、アプリケーションのあらゆる場所で明示的な条件チェックを行う必要がなくなります。

于 2010-06-27T03:53:20.493 に答える
23

スレッドがリソースを待機している場合 (RAM からレジスタへの値のロード、ディスク I/O、ネットワーク アクセス、新しいプロセスの起動、データベースへのクエリ、またはユーザー入力の待機など)、プロセッサは、リソースが利用可能になったら、最初のスレッドに戻ります。これにより、CPU がアイドル状態になる代わりに何百万もの操作を実行できるため、CPU がアイドル状態で過ごす時間が短縮されます。

ハードドライブからデータを読み取る必要があるスレッドを考えてみましょう。2014 年には、典型的なプロセッサ コアは 2.5 GHz で動作し、1 サイクルあたり 4 つの命令を実行できる可能性があります。0.4 ns のサイクル時間で、プロセッサは 1 ナノ秒あたり 10 命令を実行できます。一般的な機械式ハード ドライブのシーク時間は約 10 ミリ秒で、プロセッサはハード ドライブから値を読み取るのにかかる時間内に 1 億回の命令を実行できます。小さなキャッシュ (4 MB バッファー) を備えたハード ドライブと、数 GB のストレージを備えたハイブリッド ドライブを使用すると、パフォーマンスが大幅に向上する可能性があります。これは、シーケンシャル読み取りまたはハイブリッド セクションからの読み取りのデータ遅延が数桁速くなる可能性があるためです。

プロセッサ コアは、最初のスレッドが高レイテンシ入力 (レジスタ (1 クロック) や RAM (5 ナノ秒) よりも高価なもの) を待機している間に、スレッド間を切り替えることができます (スレッドの一時停止と再開のコストは約 100 クロック サイクルです)。ディスク I/O、ネットワーク アクセス (250 ミリ秒の遅延)、CD または低速バスからのデータの読み取り、またはデータベース呼び出し。コアよりも多くのスレッドがあるということは、待ち時間の長いタスクを解決しながら、有用な作業を実行できることを意味します。

CPU には、各スレッドに優先度を割り当てるスレッド スケジューラがあり、スレッドをスリープ状態にしてから、所定の時間後に再開することができます。スラッシングを減らすのはスレッド スケジューラの仕事です。スラッシングは、各スレッドが再びスリープ状態になる前に 100 命令しか実行しなかった場合に発生します。スレッドを切り替えるオーバーヘッドにより、プロセッサ コアの有効な合計スループットが低下します。

このため、問題を適切な数のスレッドに分割することをお勧めします。行列の乗算を実行するコードを記述している場合、出力行列のセルごとに 1 つのスレッドを作成するのは過剰かもしれませんが、出力行列の行ごとまたはn行ごとに 1 つのスレッドを作成すると、スレッドの作成、一時停止、および再開のオーバーヘッド コストが削減される可能性があります。

これが、分岐予測が重要な理由でもあります。RAM から値をロードする必要がある if ステートメントがあるが、if ステートメントと else ステートメントの本体が既にレジスタにロードされている値を使用している場合、プロセッサは条件が評価される前に一方または両方の分岐を実行する可能性があります。条件が戻ると、プロセッサは対応する分岐の結果を適用し、他の分岐を破棄します。ここで潜在的に無駄な作業を実行することは、スラッシングにつながる可能性のある別のスレッドに切り替えるよりもおそらく優れています。

クロック速度の高いシングルコア プロセッサからマルチコア プロセッサに移行したため、チップ設計は、ダイあたりのコア数を増やし、コア間のオンチップ リソース共有を改善し、分岐予測アルゴリズムを改善し、スレッド切り替えオーバーヘッドを改善することに重点を置いてきました。より良いスレッドスケジューリング。

于 2014-07-12T19:01:56.303 に答える
10

上記の回答のほとんどは、パフォーマンスと同時操作について述べています。これについては、別の角度からアプローチします。

たとえば、単純な端末エミュレーション プログラムの場合を考えてみましょう。次のことを行う必要があります。

  • リモートシステムからの着信文字を監視して表示する
  • キーボードからの入力を監視し、リモート システムに送信します。

(実際の端末エミュレーターは、入力内容をディスプレイにエコーする可能性など、さらに多くのことを行いますが、ここでは省略します。)

リモートから読み取るためのループは、次の疑似コードのように単純になりました。

while get-character-from-remote:
    print-to-screen character

キーボードを監視して送信するためのループも単純です。

while get-character-from-keyboard:
    send-to-remote character

ただし、問題は、これを同時に行う必要があることです。スレッドがない場合、コードは次のようになります。

loop:
    check-for-remote-character
    if remote-character-is-ready:
        print-to-screen character
    check-for-keyboard-entry
    if keyboard-is-ready:
        send-to-remote character

実際の通信の複雑さを考慮していないこの意図的に単純化された例でさえ、ロジックはかなり難読化されています。ただし、スレッド化を使用すると、単一のコアでも、2 つの疑似コード ループは、ロジックをインターレースすることなく独立して存在できます。どちらのスレッドもほとんどが I/O バウンドであるため、厳密に言えば、統合ループよりも CPU リソースを無駄に消費しますが、CPU に大きな負荷をかけることはありません。

もちろん、実際の使用は上記よりも複雑です。しかし、アプリケーションに懸念事項を追加すると、統合ループの複雑さが指数関数的に増加します。ロジックはますます断片化されており、ステート マシンやコルーチンなどの手法を使用して、管理しやすくする必要があります。管理可能ですが、読み取り可能ではありません。スレッド化により、コードが読みやすくなります。

では、なぜスレッド化を使用しないのでしょうか?

タスクが I/O バウンドではなく CPU バウンドである場合、スレッド化によって実際にシステムの速度が低下します。パフォーマンスが低下します。多くの場合、多くの場合。(「スラッシング」は、あまりにも多くの CPU バウンド スレッドを削除した場合によくある問題です。スレッド自体の内容を実行するよりも、アクティブ スレッドの変更により多くの時間を費やしてしまうことになります。) また、上記のロジックの理由の 1 つは、非常に単純なのは、非常に単純化された (そして非現実的な) 例を非常に意図的に選択したことです。入力した内容を画面に表示したい場合は、共有リソースのロックを導入すると、新たな問題が発生します。共有リソースが 1 つしかない場合、これはそれほど問題にはなりませんが、共有するリソースが増えるにつれて、ますます大きな問題になり始めます。

結局のところ、スレッド化には多くのことが関係しています。たとえば、すでに一部の人が言っているように、I/O バウンド プロセスの応答性を向上させることです (全体的には効率が悪くても)。また、ロジックを理解しやすくすることも目的としています (ただし、共有状態を最小限に抑える場合のみ)。それは多くのものに関するものであり、その利点が欠点を上回るかどうかをケースバイケースで判断する必要があります.

于 2010-06-27T05:10:31.183 に答える
7

ハードウェアによっては計算を高速化するためにスレッドを使用できますが、スレッドの主な用途の 1 つは、使いやすさの理由から、一度に複数の処理を行うことです。

たとえば、バックグラウンドで何らかの処理を行う必要があり、UI 入力への応答も維持する必要がある場合は、スレッドを使用できます。スレッドがないと、負荷の高い処理を実行しようとするたびにユーザー インターフェイスがハングします。

この関連する質問も参照してください:スレッドの実用的な使用法

于 2010-06-27T02:20:31.963 に答える
7

理想的な数は CPU あたり 1 スレッドであるという @kyoryu の主張には強く反対します。

このように考えてみてください: なぜマルチプロセッシング オペレーティング システムがあるのでしょうか? コンピュータの歴史のほとんどで、ほぼすべてのコンピュータに 1 つの CPU が搭載されていました。しかし、1960 年代以降、すべての「実際の」コンピューターにはマルチプロセッシング (別名マルチタスク) オペレーティング システムが搭載されていました。

複数のプログラムを実行して、他のプログラムが IO などでブロックされている間に実行できるようにします。

NT より前のバージョンの Windows がマルチタスクであったかどうかについての議論は脇に置いておきます。それ以来、すべての実際の OS はマルチタスクを備えていました。ユーザーに公開しないものもありますが、とにかくそこにあり、携帯電話のラジオを聞いたり、GPS チップと話したり、マウス入力を受け入れたりするなどのことを行います.

スレッドは、もう少し効率的なタスクです。タスク、プロセス、およびスレッドの間に基本的な違いはありません。

CPU を無駄にするのはもったいないので、できるだけ多くのものを用意しておいてください。

ほとんどの手続き型言語 (C、C++、Java など) では、適切なスレッド セーフ コードを記述するのは大変な作業であることに同意します。現在、6 コアの CPU が市場に出回っており、16 コアの CPU もそう遠くないところにあるため、マルチスレッドがますます重要な要件になっているため、人々はこれらの古い言語から離れることを期待しています。

@kyoryu との意見の相違は単なる私見であり、残りは事実です。

于 2010-06-27T04:53:23.440 に答える
5

任意の数の要求を処理する必要がある Web サーバーを想像してください。リクエストを並行して処理する必要があります。そうしないと、新しいリクエストはすべて、他のすべてのリクエストが完了するまで待機する必要があるためです (インターネット経由でのレスポンスの送信を含む)。この場合、ほとんどの Web サーバーは、通常処理するリクエストの数よりもはるかに少ないコアを持っています。

また、サーバーの開発者にとっても簡単になります。リクエストを処理するスレッド プログラムを作成するだけで済み、複数のリクエストの格納や処理する順序などについて考える必要がありません。

于 2010-06-27T02:25:23.073 に答える
3

多くのスレッドがスリープ状態になり、ユーザー入力、I/O、およびその他のイベントを待機します。

于 2010-06-27T09:54:43.773 に答える
2

スレッドは、UI アプリケーションの応答性に役立ちます。さらに、スレッドを使用して、コアからより多くの作業を引き出すことができます。たとえば、単一のコアで、1 つのスレッドで IO を実行し、別のスレッドで計算を実行できます。シングルスレッドの場合、コアは基本的にアイドル状態で、IO が完了するのを待っている可能性があります。これはかなり高レベルの例ですが、スレッドを使用して CPU を少し強化することは間違いありません。

于 2010-06-27T02:26:06.333 に答える
2

一部の API の設計方法では、それらを別のスレッド (ブロック操作を伴うもの) で実行するしかありません。例としては、Python の HTTP ライブラリ (AFAIK) があります。

通常、これは大した問題ではありません (問題がある場合、OS または API は代替の非同期操作モード、つまり: で出荷する必要がありますselect(2))。これはおそらく、I/ の待機中にスレッドがスリープ状態になることを意味するためです。 〇完成。一方、何かが重い計算を行っている場合は、GUI スレッドなどとは別のスレッドに配置する必要があります (手動での多重化を楽しむ場合を除きます)

于 2010-06-27T03:42:19.573 に答える
2

プロセッサーまたは CPU は、システムに接続されている物理チップです。プロセッサは複数のコアを持つことができます (コアは、命令を実行できるチップの一部です)。コアが複数のスレッドを同時に実行できる場合、コアはオペレーティング システムから複数の仮想プロセッサとして認識されます (スレッドは 1 つの命令シーケンスです)。

プロセスは、アプリケーションの別名です。通常、プロセスは互いに独立しています。1 つのプロセスが停止しても、別のプロセスが停止することはありません。プロセスが通信したり、メモリや I/O などのリソースを共有したりすることは可能です。

各プロセスには、個別のアドレス空間とスタックがあります。プロセスには複数のスレッドを含めることができ、それぞれが命令を同時に実行できます。プロセス内のすべてのスレッドは同じアドレス空間を共有しますが、各スレッドには独自のスタックがあります。

うまくいけば、これらの定義と、これらの基礎を使用したさらなる研究が理解に役立つことを願っています.

于 2010-06-27T02:50:31.080 に答える
1

実際、スレッドの理想的な使用法は、コアごとに 1 つです。

ただし、非同期/非ブロッキング IO のみを使用しない限り、ある時点でスレッドが IO でブロックされ、CPU を使用しない可能性が高くなります。

また、典型的なプログラミング言語では、CPU ごとに 1 つのスレッドを使用することはやや困難です。並行処理を中心に設計された言語 (Erlang など) を使用すると、余分なスレッドを使用しなくて済むようになります。

于 2010-06-27T02:25:55.430 に答える
1

最初の推測に応えて: マルチコア マシンは、1 つのプロセスの複数のスレッドだけでなく、複数のプロセスを同時に実行できます。

最初の質問への回答: 通常、複数のスレッドのポイントは、1 つのアプリケーション内で複数のタスクを同時に実行することです。ネット上の古典的な例は、メールを送受信する電子メール プログラムと、ページ要求を送受信する Web サーバーです。(Windows のようなシステムを 1 つのスレッドのみ、または 1 つのプロセスのみを実行するように縮小することは本質的に不可能であることに注意してください。Windows タスク マネージャーを実行すると、通常、アクティブなプロセスの長いリストが表示され、その多くは複数のスレッドを実行します。 )

2 番目の質問への回答: ほとんどのプロセス/スレッドは CPU バウンドではありません (つまり、連続して中断されずに実行されません)。代わりに、I/O が完了するまで頻繁に停止して待機します。その待機中、他のプロセス/スレッドは、待機中のコードから「盗む」ことなく実行できます (シングルコアマシンでも)。

于 2010-06-27T05:21:37.247 に答える
-3

スレッドは、一連の操作と同じくらい単純なコードを記述できるようにする抽象化であり、コードが他のコードとインターレースされて実行されていることを幸いなことに認識していないか、IO を待機して待機している、または他のスレッドのスレッドを待機している (おそらくは多少意識している) ことを気にしません。イベントやメッセージ。

于 2011-08-26T14:17:47.917 に答える
-8

ポイントは、大多数のプログラマーがステート マシンの設計方法を理解していないということです。すべてを独自のスレッドに入れることができるため、プログラマーは、進行中のさまざまな計算の状態を効率的に表現して、中断して後で再開できるようにする方法を考える必要がなくなります。

例として、非常に CPU を集中的に使用するタスクであるビデオ圧縮について考えてみましょう。GUI ツールを使用している場合は、おそらくインターフェイスの応答性を維持したいでしょう (進行状況の表示、キャンセル要求への応答、ウィンドウのサイズ変更など)。そのため、一度に大きな単位 (1 つまたは複数のフレーム) を処理し、UI とは別の独自のスレッドで実行するようにエンコーダ ソフトウェアを設計します。

もちろん、進行中のエンコード状態を保存して、プログラムを閉じて再起動したり、リソースを大量に消費するゲームをプレイしたりできると便利だと気づいたら、ステート マシンの設計方法を始まり。それか、OS をプロセス休止状態にするというまったく新しい問題を設計して、個々のアプリを一時停止してディスクに再開できるようにすることにします...

于 2010-06-27T09:37:50.143 に答える