「マルチコア」フレンドリーではないと主張するプログラム


17

このフレーズまたは類似のフレーズは、時々発生します。一般的に、マルチコアプロセッサを最大限に活用するように設計されていないと主張するプログラムを指します。これは、特にビデオゲームプログラミングで一般的です。(もちろん、基本的なスクリプトなど、多くのプログラムには並行性がなく、それを必要としません)。

どうすればいいの?多くのプログラム(特にゲーム)は本質的に同時実行を使用し、OSはCPUのタスクスケジューリングを担当しているため、これらのプログラムは本質的に利用可能な複数のコアを利用していませんか?この文脈で「複数のコアを活用する」とはどういう意味ですか?これらの開発者は、実際にOSタスクのスケジューリングを禁止し、アフィニティまたは独自のスケジューリングを強制していますか?(大きな安定性の問題のように聞こえます)。

私はJavaプログラマーなので、抽象化やその他の理由でこれに対処する必要はなかったかもしれません。


11
大きな可能性は、シングルプロセッサ/コアシステムでは機能しますが、複数のプロセッサ/コアの真の同時実行性を損なうショートカットが同期で使用されたことです。
バートヴァンインゲン

@BartvanIngenSchenau:これは正しいです。これを展開し、回答として投稿してください。他のすべての人はポイントを逃したと思います。
ケビンクライン14

1
@Bartは本当に近いと思います。ただし、s / work /は動作しているように見え、マークに近づきます。
ベンフォイト14

余談として-私はこれをプログラマではなくユーザーとして経験しました-Windows XPのGround Control 2。マルチコアシステムのコアアフィニティを適切に実行するにはコアアフィニティを1つだけに設定する必要があります。そうしないと、すべてのアニメーション(ゲーム全体)が10倍の速度で実行されます。 。私はゲームの仕事をしたことはありませんが、私の考えでは、ゲームの一部は、プロセッサが同時に一定量の仕事をしていることに依存しているように見えました。
ジャミーピーチ14

回答:


28

良好な同時実行性は、アプリケーションにいくつかのスレッドを投げて最高のものを期待する以上のことを必要とします。プログラムが並外れた並列処理から純粋な順次処理に移行する方法には幅があります。どのプログラムでも、アムダールの法則を使用して、問題またはアルゴリズムがどれだけスケーラブルであるかを表現できます。恥ずかしいほど並列アプリケーションのいくつかの資格は次のとおりです。

  • 共有状態はありません。すべての関数は、渡されたパラメーターにのみ依存します
  • 物理デバイス(グラフィックカード、ハードドライブなど)へのアクセスなし

他の資格もありますが、これらの2つだけで、特にゲームが複数のコアを利用するのが簡単だと思わない理由を理解できます。1つは、異なる関数が物理学、動きを計算し、人工知能を適用するなど、レンダリングされる世界のモデルを共有する必要があります。2つ目は、このゲームモデルの各フレームをグラフィックカードで画面にレンダリングする必要があります。

公平を期すために、多くのゲームメーカーは、サードパーティ製のゲームエンジンを使用しています。しばらく時間がかかりましたが、これらのサードパーティのゲームエンジンは、以前よりはるかに並列になりました。

効果的な同時実行性に対処するには、アーキテクチャ上の大きな課題があります

並行性は、バックグラウンドでのタスクの実行から並行性の完全なアーキテクチャサポートまで、多くの形式をとることができます。一部の言語では、ERLANGなどの非常に強力な同時実行機能が提供されますが、アプリケーションの構築方法については非常に異なる考え方が必要です。

すべてのプログラムが完全なマルチコアサポートの複雑さを実際に必要とするわけではありません。そのような例の1つは、税務ソフトウェア、または任意のフォーム駆動型アプリケーションです。あなたの時間のほとんどがユーザーが何かをするのを待つことに費やされるとき、マルチスレッドアプリケーションの複雑さはそれほど有用ではありません。

一部のアプリケーションは、Webアプリケーションなど、より厄介な並列ソリューションに適しています。この場合、プラットフォームは恥ずかしいほど並行して開始され、スレッドの競合を課す必要はありません。

要点:

複数のスレッド(つまりコア)を利用しないことで、すべてのアプリケーションが実際に損害を受けるわけではありません。それによって傷つけられるものについては、計算が並列処理に適していないか、それを調整するためのオーバーヘッドがアプリケーションをより脆弱にする場合があります。残念ながら、並列処理はまだうまくいくべきほど簡単ではありません。


これは素晴らしい分析です。私はしかし、現実世界のプログラムについてのあなたのポイントは、多くの場合、あるバグということの一つは、あきれるほど並列化することは難しい平行とされていない:行うことは不可能かもしれないが、同じ並列に事を、それが行うには非常に簡単かもしれ異なる(並列に物事を例:パイプラインアーキテクチャ内、または別のUIスレッド)。
アモン14

8
本当のポイントは、並列実行のために設計する必要があるということです。そうしないと、設計の不足に制約されます。私はあることに同意することができなく、それは高いユーザーの期待を持つ既存のアプリケーションの場合、並行して別のことを行うことは非常に簡単です。その場合、それを可能にするために書き換えが非常によく必要かもしれません。書き換えは本質的にリスクを伴いますが、時折、それらに対して適切な議論をすることができます。可能な限り多くのコードを保持しながら、並列処理を最大化するような書き直しをいくつか実行しました。ありますたくさん隠された要因のは。
ベリンロリチュ14

素晴らしい答え。一部のシステムを並列化すると収益が減少する可能性があるだけでなく、システムを並列化するために必要なオーバーヘッドのために実際に低速になる場合があることを強調する価値があります。特に、多くのセマフォ/ロックとコンテキスト切り替えがランタイムに悪影響を与える可能性があります。特にコンテキストの切り替えは、キャッシュの有効性を低下させる可能性があります。これは、システムを最適化する段階にある場合、重要な懸念事項です。特にゲームエンジンのOPの例から、並列アクセスよりもキャッシュの最適化について多くのことを聞いたことを思い出します。
ガンクロ14

35

多くのプログラム(特にゲーム)は本質的に並行性を使用していますが、

いいえ、実際は逆です。ほとんどのアプリはシングルスレッドマインドセットで記述されており、開発者は並行性をサポートするために必要な変更を行っていません。

C、C ++、およびC#では、新しいスレッドやプロセスを開始するようにアプリケーションに明示的に指示する必要があります。

あなたはスレッドのスケジューリングに集中しすぎており、潜在的なスレッド内のデータ処理に十分ではないと思います。スレッドやプロセス間でデータを共有するには、何らかの同期が必要です。複数のスレッドを使用するようにアプリケーションを変更しても、その同期が適切に行われないと、コード内のバグを追跡するのが非常に難しくなる可能性があります。

私が取り組んできたマルチスレッドアプリケーションの場合、通常はディスパッチについては心配せず、データの同期についてのみ心配しました。ディスパッチについて心配しなければならなかったのは、誤ったデータ同期のために競合状態を追いかけていたときだけでした。

一般に、アプリケーションが複数のコアを使用できないと言った場合、データ操作を保護するための同期が行われていないことを意味します。


これは、大規模な開発者/出版社からの新しい近代的なプログラムにも当てはまりますか?座ってプログラムを書くとき、私が考える設計段階の最初のことの1つは、並行性が必要かどうかです。その結果、設計が大幅に異なる可能性があるためです。特にゲームにはある程度の並行性が必要です。そうしないと、画面上の1000のモデルのうちの1つが何かを実行しようとしたときにゲームがフリーズします。
SnakeDoc 14

5
@SnakeDoc-ドメインが混乱していると思います。ビッグゲーム企業は並行性を念頭に置いて書いていることは間違いありませんが、並行ゲームをサポートしていないビッグゲームのゲームはまだ見ていません。私が見た並行性をサポートできないアプリとゲームは、一般的に、そのような考え方からは開始しなかった小規模なショップ/個々の開発者のものです。そして、アプリケーションの進化のある時点で、事実の後に並行性を確保することが不可能になります。また、一部のアプリは、同時であることを正当化するのに十分なことを意図していませんでした。

また、一部のゲームは、ゲームエンジン(コード実装)を更新することなく、新しいコンテンツ(グラフィックスとゲームプレイ)で成功します。したがって、ゲームエンジンの技術は何年も遅れている可能性があります。
rwong 14

6
@SnakeDoc:数千の画面モデルを処理するために並行性は必要ありません。ゲーム内のすべてのオブジェクトがそれをシミュレートするために独自のスレッドを必要とするわけではありません。1つのスレッドで、タイムステップごとに画面上のすべての更新を処理できます。
user2357112は、Monicaを14

13

これは、複数のスレッドに関するものであるため、複数のコアに関するものではありません。OSは、任意のコアで実行するスレッドをスケジュールする場合があり、このスケジュールは、スケジュールされているプログラムに対して透過的です。ただし、多くのプログラムは複数のスレッドを使用して記述されていないため、一度に1つのコアでしか実行できません。

なぜシングルスレッドのプログラムを書くのですか?それらは書くのがより簡単で、デバッグもより簡単です:複数の事柄が一度に起こり、お互いの方法で可能になるのではなく、ある事柄が次々に起こります。または、プログラムがマルチコアマシンをターゲットにしていない可能性があります(古いゲームの場合のように)。場合によっては、コンテキスト切り替えとスレッド間の通信のオーバーヘッドが並列実行によって得られる速度を上回る場合、マルチスレッドプログラムはシングルスレッドバージョンよりも遅く実行される可能性があります(プログラムの一部は並列​​化できない場合があります)。


8

これは完全な答えではありません。それは警告物語です。

ある日、並行プログラミングコースの学生に並列クイックソートを見せようと思いました。クイックソートはうまく並列化すべきだと思いました。2つのスレッドを使用しました。シングルコアコンピューターで実行しました。結果は次のとおりです。

  • シングルスレッドバージョンの場合は14秒。
  • 2スレッドバージョンの場合は15秒。

これは私が期待したことについてでした。

次に、新しいデュアルコアマシンで試しました。

  • シングルスレッドバージョンの場合は11秒。
  • 2スレッドバージョンの場合は20秒。

2つのスレッドは、残りのタスクのキューを共有しました。キューオブジェクトのフィールドは、一方のコアのキャッシュと他方のキャッシュとの間で前後にシャッフルされていたようです。


2
何個の配列要素をテストしましたか?キャッシュラインの競合を避けるために、マルチコアプログラミングではデータのコピーが必要になるため、おそらくマージソートの方が適しているでしょうか?
rwong 14

2
@rwong 10,000,000の配列要素がありました。確かにmergesortはうまく並列化されます。マージソートを使用していた場合、有用なレッスンを学習できなかったでしょう。
セオドアノーベル14

1
@ArlaudPierreアルゴリズムの並列化を検討します。クイックソートは、バッグオブタスクアプローチを使用できるため、興味深いものです。タスクは独立しているので、私の直感では、それは恥ずかしい並列処理の例であるべきだということでした。私は、チューニングのビットの後、それが実際に近い2へのスピードアップだ、それを言及する必要があります
セオドアNorvell

1
@Jules答えは負荷分散です。また、スレッドの数を簡単に変更できるように書きたいと思いました。あなたのアプローチは2のべき乗にうまく一般化しますが、他のスレッド数にはあまり良くありません。
セオドアノーベル14

2
@MaciejPiechotka道徳はあなたが提案するほとんどすべてのものです。しかし、OPに戻ると、最も関連するモラルは、そうでないことを保証するための努力が費やされない限り、マルチスレッドプログラムが実際にシングルコアプロセッサよりもマルチコアアーキテクチャで(かなり)遅く実行される可能性があることだと思います。
セオドアノーベル14年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.