コアの数がN未満のCPUで実行すると正常に動作しないコード(またはコードの一部ではなく完全なソフトウェア)を作成することはできますか? Without明示的にチェックし、故意に失敗します:
IF(noOfCores <4)THENが意図的に適切に実行されない
ゲームの(Dragon Age:Inquisition)最小システム要件を調べていますが、最小4コアCPUと記載されています。多くのプレイヤーは、2コアのCPUでは動作せず、2つの物理コアと2つの論理コアがある Intel Core i3s ではEVENは動作しないと言っています。そして、それは計算能力の問題ではありません。
私の理解では、スレッドはOSによってCPUから完全に分離されています。
物事を片付けるために:
私は[〜#〜]ではありません[〜#〜]で、「コードからCPUコアの数を調べて、意図的に失敗することはできますか? 」 ...そのようなコードは意図が間違っています(計算能力を必要とせずに、プログラムを実行するために、より高価なCPUを購入せざるを得ません)。私のコードには、たとえば4つのスレッドがあり、2つのスレッドが同じ物理コアで実行されると失敗する(システム情報を明示的にチェックせず、意図的に失敗しない)。
要するに、複数のコアから得られる追加の計算能力を必要とせずに、複数のコアを必要とするソフトウェアはありますか? N個の物理コアが必要になるだけです。
コアアフィニティを不注意に使用すると、「偶然」にこれを実行できる可能性があります。次の疑似コードを考えてみます。
2コアCPUでこれらのうち4つを開始すると、コアアフィニティ設定に問題が発生するか、2つのスレッドが使用可能なコアを占有し、2つのスレッドがスケジュールされないことになります。コアの合計数を明示的に尋ねたことはありません。
(実行時間の長いスレッドがある場合、CPUアフィニティを設定すると、一般にスループットが向上します)
ゲーム会社が正当な理由なくより高価なハードウェアを購入するように「強制」しているという考えはあまり妥当ではありません。顧客を失うだけです。
編集:この投稿は33の賛成票を獲得しました。これは、経験に基づく推測に基づいているため、かなりの数です。
人々は、DA:Iをデュアルコアシステムで実行するようにしています。 http://www.dsogaming.com/pc-performance-analyses/dragon-age-inquisition-pc-performance-分析/ この分析では、ハイパースレッディングをオンにすると状況が大幅に改善されると述べています。 HTが命令発行ユニットまたはキャッシュを追加しないことを考えると、HTは1つのスレッドがキャッシュストール内にある間に実行を許可するだけであり、スレッドの数に純粋にリンクしていることを強く示唆しています。
別のポスターは、グラフィックスドライバーの変更が機能すると主張しています: http://answers.ea.com/t5/Dragon-Age-Inquisition/Working-solution-for-Intel-dual-core-CPUs/td-p/ 3994141 ;グラフィックスドライバーはスカムとビラニーの悲惨なハイブである傾向があることを考えると、これは驚くべきことではありません。悪名高いドライバセットの1つに、QUAKE.EXEから呼び出された場合に選択される「正解と低速」モードと「高速と不正解」モードがありました。見かけ上のCPUの数が異なると、ドライバーの動作が異なる可能性があります。おそらく(推測に戻ると)、別の同期メカニズムが使用されます。 spinlocks の誤用
「ロックおよび同期プリミティブの誤用」は、非常に一般的なバグの原因です。 (これを書いているときに私が仕事で見ているはずのバグは、「印刷ジョブの終了と同時にプリンター設定を変更するとクラッシュする」です)。
編集2:コメントには、OSがスレッドの枯渇を回避しようとしていることが記載されています。ゲームにはスレッドに作業を割り当てるための独自の内部準スケジューラーがあり、グラフィックスカード自体にも同様のメカニズムがあります(これは事実上、独自のマルチタスクシステムです)。それらの1つまたはそれらの間の相互作用のバグの可能性は非常に高いです。
www.ecsl.cs.sunysb.edu/tr/ashok.pdf(2008)は、グラフィックカードのより良いスケジューリングに関する卒業論文であり、通常、先着順のスケジューリングを使用することを明示的に述べており、これは実装が簡単です。非先制システム。状況は改善しましたか?おそらく違います。
アプリケーションは4つのタスクを並列スレッドで実行し、ほぼ同時に完了することを期待しているため、4つのコアが必要になる場合があります。
すべてのスレッドが別々のコアによって実行され、すべてのスレッドがまったく同じ計算ワークロードを持っている場合、それらはほぼ同じ時間で終了する可能性が非常に高くなります(ただし、保証はされていません)。ただし、2つのスレッドが1つのコアで実行される場合、コアは常に2つのスレッド間でコンテキストを切り替えるため、タイミングの予測がはるかに難しくなります。
予期しないスレッドタイミングが原因で発生するバグは、「 競合状態 」と呼ばれます。
ゲーム開発のコンテキストでは、この種の問題のあるもっともらしいアーキテクチャは、ゲームのさまざまな機能がさまざまなCPUスレッドによってリアルタイムでシミュレートされるアーキテクチャである可能性があります。各機能が独自のコアで実行される場合、それらはすべてほぼ同じ速度でシミュレーションされます。ただし、2つの機能が1つのコアで実行される場合、両方のシミュレーションは他のゲームワールドの半分の速度でしか行われず、あらゆる種類の奇妙な動作を引き起こす可能性があります。
特定のタイミングで実行される独立したスレッドに依存するソフトウェアアーキテクチャは非常に脆弱であり、並行プログラミングに対する理解が非常に悪いことを示しています。これらの種類の問題を防ぐためにスレッドを明示的に同期するために、事実上すべてのマルチスレッドAPIで使用可能な機能があります。
これらの「最小要件」がそれ以下ではゲームが実行されないことを表す可能性は低いです。はるかに可能性が高く、それを下回るとゲームが許容可能なパフォーマンスで実行されないものを表します。ソフトウェアが技術的に実行できたとしても、シングルコアの1 Ghzボックスで実行しているとき、くだらないパフォーマンスについて不満を言う多くの顧客に対処するゲーム会社はありません。したがって、おそらく、許容できるパフォーマンスを提供するよりも少ないコア数のボックスでは、意図的にハードフェイルするように設計されています。
ゲームパフォーマンスの重要な指標の1つはフレームレートです。通常、1秒あたり30または60フレームで実行されます。つまり、ゲームエンジンは、一定の時間内にゲームの状態から現在のビューをレンダリングする必要があります。 60 fpsを達成するために、これを行うには16ミリ秒を少し超えています。ハイエンドのグラフィックスを備えたゲームはCPUに非常に制限されているため、より高い品質をプッシュしようとすること(時間がかかる)とこの時間予算を維持する必要性との間には、大きなギブアンドテイクがあります。したがって、各フレームのタイムバジェットは非常にタイトです。
時間の予算が限られているため、開発者は1つ以上のコアへの排他的アクセスを望んでいます。彼らはまた、その時間予算で行わなければならないものであるため、コアでレンダリングスタッフを独占的に実行できるようにしたいと思うかもしれません。侵入する。
理論的には、これらすべてを単一のコアに詰め込むこともできますが、その後、すべてがはるかに困難になります。突然、すべてのゲーム状態が十分に速く発生し、レンダリングが発生することを確認する必要があります。 OSに「スレッドAがスレッドBの処理に関係なくXの量の作業を16ミリ秒で完了する必要がある」ことを理解させる方法がないため、これらを2つのソフトウェアスレッドにすることはできません。
ゲーム開発者は、新しいハードウェアを購入させることにまったく関心がありません。彼らがシステム要件を持っている理由は、ローエンドマシンをサポートするコストはそれだけの価値がないからです。
スリープしない3つのリアルタイムスレッドと1つの他のスレッド。コアが4つ未満の場合、4番目のスレッドは実行されません。 4番目のスレッドがリアルタイムスレッドの1つと通信して、リアルタイムスレッドが終了する必要がある場合、コードは4つ未満のコアで終了しません。
明らかに、リアルタイムスレッドがスリープを許可しない何か(スピンロックなど)を待機している場合、プログラム設計者は失敗しました。
まず第一に、ソフトウェアスレッドはハードウェアスレッドとは何の関係もなく、しばしば混同されます。ソフトウェアスレッドは、ディスパッチしてプロセスコンテキスト内で独自に実行できるコードです。ハードウェアスレッドは主にOSによって管理され、通常のプログラムについて話すとき、プロセッサのコアにディスパッチされます。これらのハードウェアスレッドは、負荷に基づいてディスパッチされます。ハードウェアスレッドディスパッチャーは、ロードバランサーのように機能します。
ただし、ゲーム、特にハイエンドゲームの場合、ハードウェアスレッドがゲーム自体によって管理される場合や、ゲームがハードウェアスレッドディスパッチャーに何をするかを指示する場合があります。これは、すべてのタスクまたはタスクのグループが通常のプログラムのように同じ優先度を持たないためです。ドラゴンエイジはハイエンドのゲームエンジンを使用するハイエンドのゲームスタジオに由来するため、「手動」ディスパッチを使用し、コアの数が最小限のシステム要件になると想像できます。 1つまたは2つのコアしかないマシンで実行されている3番目の物理コアにコードを送信すると、プログラムがクラッシュします。
Virtualizeを使用して物理コアよりも多くの仮想コアを持つことが可能であり、ソフトウェアはそれがvirtualizeで実行されていることを認識せず、代わりに多くの物理コアを持っていると考えるので、そのようなソフトウェアは不可能だと思います。
つまり、常にNコア未満で停止するソフトウェアを作成することはできません。
他の人が指摘したように、特にN個のプロセスが<N個のプロセッサで実行されているときに、使用中のOSとコードが競合状態に対してほとんど保護されていない場合に、潜在的にチェックできるソフトウェアソリューションがあります。本当のトリックは、Nプロセッサ未満の場合に失敗し、NプロセッサがあってもN未満のプロセッサに作業を割り当てる可能性のあるOSがある場合は失敗しないコードです。
3つのスレッドが何かを実行して(バックグラウンドを生成するか、NPC移動)を生成して)イベントを4番目のスレッドに渡している可能性があります。 4番目のスレッドがすべてのイベントを取得しない(コアでスケジュールされていないため)場合、ビューモデルは正しく更新されません。これは散発的にのみ発生する可能性がありますが、これらのコアはいつでも利用可能である必要があります。 CPU使用率が常に高いわけではないのに、ゲームが正常に機能しない理由。
ジョシュアは正しい道を進んでいると思いますが、それは結論ではありません。
できる限り多くのことを実行するように記述された3つのスレッドがあるアーキテクチャがあるとします。これらのスレッドのパフォーマンスを維持するために、何も制御を解放しないでください。Windowsタスクスケジューラからの遅延を危険にさらしたくありません。 4つ以上のコアがある限り、これは正常に動作しますが、存在しない場合は失敗します。
一般に、これは悪いプログラミングですが、ゲームは別の問題です。すべてのハードウェアで劣っている設計か、十分に優れたハードウェアで優れている設計か、劣っているハードウェアでの障害かという選択に直面した場合、ゲーム開発者は通常、ハードウェアが必要です。
Is it possible to write code (or complete software, rather than a piece of code) that won't work properly when run on a CPU that has less than N number of cores?
もちろんです。リアルタイムスレッドの使用は、これが可能であるだけでなく、ジョブを実行するための望ましい方法(多くの場合、唯一の正しい方法)である状況の良い例です。ただし、通常、リアルタイムスレッドはOSカーネルに制限されます。通常、ドライバーは、ある種のハードウェアイベントが定義された期間内に処理されることを保証できる必要があります。通常のユーザーアプリケーションでリアルタイムスレッドを使用することはできません。また、Windowsユーザーモードアプリケーションでリアルタイムスレッドを使用できるかどうかさえわかりません。一般に、オペレーティングシステムでは、特定のアプリケーションがシステムの制御を引き継ぐことができるため、ユーザーランドからこれを行うことは意図的に不可能になっています。
ユーザーランドのアプリケーションに関して:実行するために特定の数のスレッドをチェックすることは、意図的に悪意があるとの仮定は正しくありません。たとえば、自分自身にコアを必要とする、長時間実行されるパフォーマンス集約型のタスクが2つあるとします。 CPUコアの速度に関係なく、他のスレッドとコアを共有すると、スレッドの切り替えによって発生する通常のペナルティ(相当なもの)に加えて、キャッシュのスラッシングが原因で、許容できない深刻なパフォーマンスの低下となる可能性があります。この場合、それは完全に妥当です。特にゲームの場合、これらの各スレッドを特定の1つのコアのみにアフィニティを持つように設定し、他のすべてのスレッドがそれらの2つのコアにアフィニティを持たないように設定します。ただし、これを行うには、システムに2つ以上のコアがあることを確認し、そうでない場合は失敗するようにする必要があります。
顕著な量のロック競合を伴うスピンロックを使用するコードは、ひどく(ゲームのようなアプリケーションでは-「できない」という程度に)実行されます)スレッドの数がコアの数を超える場合。
たとえば、4つのコンシューマスレッドを処理するキューにタスクを送信するプロデューサスレッドを想像してみてください。コアは2つしかありません。
プロデューサーはスピンロックを取得しようとしますが、他のコアで実行されているコンシューマーによって保持されています。 2つのコアは、プロデューサーが回転し、ロックが解放されるのを待機している間、ロックステップを実行しています。これはすでに悪いですが、それが得るほど悪くはありません。
残念ながら、コンシューマスレッドはタイムクォンタムの終わりにあるため、プリエンプトされ、別のコンシューマスレッドがスケジュールされます。ロックを取得しようとしますが、もちろんロックが取得されるため、2つのコアが回転し、起こり得ない事態を待機しています。
プロデューサースレッドがタイムスライスの終わりに到達し、プリエンプトされ、別のコンシューマーがウェイクアップします。繰り返しになりますが、2つのコンシューマがロックが解放されるのを待っています。それは、さらに2つのタイムクォンタムが経過するまで発生しません。
[...]最後に、スピンロックを保持していたコンシューマがロックを解放しました。それは、他のコアで回転している人がすぐに取得します。 75%の確率(3対1)で、別のコンシューマースレッドである可能性があります。言い換えれば、プロデューサーがまだ停止している可能性は75%です。もちろん、これは消費者も失速することを意味します。プロデューサーがタスクを調停しなければ、彼らは何もすることがありません。
これは原則として、スピンロックだけでなく、あらゆる種類のロックで機能しますが、CPUが何も実行しない間、CPUがサイクルを燃焼し続けるため、スピンロックでは壊滅的な影響が顕著になります。
上記に加えて、一部のプログラマーが最初のコアにアフィニティーを設定した専用スレッドを使用するという素晴らしいアイデアを持っていると想像してください。そのため、RDTSCはすべてのプロセッサーで信頼できる結果を提供します(とにかく、そうは思わない人もいます)。