web-dev-qa-db-ja.com

ソフトウェアプログラミングで、CPUとGPUの両方の負荷を100%にすることは可能ですか?

これは、ゲーマーとして興味深いと思ったテーマに関する一般的な質問です。CPU/ GPUのボトルネックとプログラミングです。誤解しない限り、CPUとGPUの両方が計算することを理解するようになりましたが、アーキテクチャの違いにより、一部の計算は他の計算よりも優れています。たとえば、クラックハッシュや暗号通貨マイニングは、CPUよりもGPUの方がはるかに効率的です。

だから私は疑問に思いました:CPUが(たとえば)50%であるのにGPUが100%の負荷であるのは避けられないのですか?

または、より正確には最初の計算が100%の負荷であり、両方が100%の負荷に到達する場合、GPUによって通常実行される一部の計算をCPUで実行できますか?

私は主題について少し調べましたが、まったく手ぶらで戻ってきました。私はこれがこのサブセクションに配置され、あなたが私に与えるかもしれないあらゆるドキュメントや講義に開かれていると思います!

43
MadWard

理論的にはそうですが、実際にはそれだけの価値はほとんどありません。

CPUとGPUはどちらも turing-complete であるため、一方で計算できるアルゴリズムは、もう一方でも計算できます。問題は、どれほど速く、どれほど便利かです。

GPUは、大規模なデータセットの多くのデータポイントに対して同じ単純な計算を行うのに優れていますが、CPUは、多くの分岐を伴うより複雑なアルゴリズムに適しています。ほとんどの問題で、CPUとGPUの実装間のパフォーマンスの違いは非常に大きくなります。つまり、ストールしているときに一方を使用して他方から作業を行っても、パフォーマンスが大幅に向上するわけではありません。

ただし、これに対して支払う必要がある代償は、すべてを2回プログラムする必要があることです。1回はCPUに対して、もう1回はGPUに対してです。また、切り替えと同期のロジックも実装する必要があるため、作業量は2倍以上になります。その動作は現在の負荷に依存するため、そのロジックをテストすることは非常に困難です。このスタントからバグを再現することは非常にあいまいで不可能であることを期待してください。

62
Philipp

ゲームプログラミングとは関係ありません。一部の科学コードは、GPUとCPUの両方を使用することもできます。

注意深くそして苦痛なプログラミングで、例えば OpenCL または [〜#〜] cuda [〜#〜] を使用すると、GPUとCPUの両方をほぼ100%ロードできます。おそらく、GPU(いわゆる「カーネル」コード)とCPU、およびいくつかの退屈なグルーコード(特に、コンパイルされたカーネルコードをGPUに送信するため)には異なるコードを記述する必要があります。

ただし、コードは複雑になるため、特にGPUとCPU間のデータ転送にはコストがかかるため、実行している特定のハードウェアに合わせて調整する必要がある可能性があります。

ヘテロジニアスコンピューティング の詳細をご覧ください。

GCCの最近のバージョンでサポートされている OpenACC も参照してください(例: GCC 6 2016年6月)

36

スーパーコンピューティングの観点からは、CPU/GPU負荷をパーセンテージで考えるのではなく、問題の必要な操作の数を決定し、それをシステムのピークパフォーマンスと比較することをお勧めします。

CPU使用率が100%になっても、必ずしもシステムのすべてのパフォーマンスが得られるわけではありません。多くの場合、CPUは複数の異なる処理を同時に実行できます(除算と加算など)。除算を早期に開始できる場合は、追加と重複する可能性があります。デスクトップCPUには、out-of-order unitがあり、このようなオーバーラップからメリットを得るためにステートメントを並べ替えます。または、次のプログラムがある場合:

if (expr1)
    expr2;
else
    expr3;

並べ替えCPUは、3つの式を同時に計算し、それらの1つの結果を破棄します。これにより、全体的に速くなります。プログラムに何らかのブロッカーがあり、並べ替えできない場合は、CPUで使用するレーンが少なくなっていますが、おそらく100%のままです。

次に、CPUにベクトル演算であるSIMD機能があります。通常、同時に4つまたは8つの操作しかありませんが、GPUは32または64のように動作するという意味で、GPGPU-lightに似ています。それでも、FLOPSをクランキングするためにそれを使用する必要があります。

偽の共有のようなものは、通常Linuxでカーネルの負荷として現れる、非常に大きな同期コストにつながる可能性があります。 CPUは完全に使用されていますが、有効なスループットはあまりありません。

IBM Blue Gene/Qマシンでプログラミングを行っています。これは多くの階層レベル( 古いBlue Gene/Lの概略図 )を持っているため、効率的にプログラムするのは困難です。パフォーマンスを引き出すためには、SIMDおよびSMT(インテルはこれをハイパースレッディングと呼びます)までの完全な階層を使用する必要があります。

そして、ネットワークはしばしばあなたを制限します。したがって、ネットワーク経由で通信するよりも、複数のCPUで同時に計算する方が(ウォールクロック)時間で高速であることがわかります。これにより、CPUへの負荷が増え、プログラムの実行が高速になります。しかし、実際のプログラムのスループットは、生の数値から見えるほどには良くありません。

ミックスにGPUを追加すると、パフォーマンス全体を実現するためにこの全体を調整することがさらに困難になります。これは、2か月以内にラティスQCD修士論文で始めることの1つになります。

11
Martin Ueding

Mozilla Researchで開発されている Servo ブラウザエンジン、より具体的には Webレンダー(ビデオ)

他の回答(特に@Philipの回答)で述べられているように、タスクをCPUからGPUに動的にシフトすることは非現実的かもしれませんが、一般的なワークロードでのCPU/GPUの負荷を事前に調査して切り替えることは現実的ですsomeタスクを一般的に負荷の少ないタスクに割り当てます。

Webレンダーの場合、目新しいのは、従来のブラウザーがほとんどのレンダリング作業をCPUで実行することです(つまり、CPUは、表示するオブジェクト、カットする場所などを計算するために使用されます)。通常、GPUの方が優れています。ただし、すべてのユースケースが簡単に実装できるわけではありません(部分的なカリング、シャドウなど)。

Webレンダーの初期バージョンは、パフォーマンスの向上に非常に成功したことが判明しましたが、テキストレンダリングの問題に対処しようとはしませんでした(他にもいくつかの制限がありました)。 Mozilla Researchは、制限を少なくすること、特にテキストレンダリングをサポートすることを目的とした2つ目のバージョンに取り組んでいます。

もちろん、目標は、可能な限りレンダリングプロセスの負荷をGPUにオフロードして、CPUがJavascriptを実行したり、DOMを更新したり、その他すべてのタスクを実行できるようにすることです。

したがって、あなたの提案ほど極端ではありませんが、CPUとGPUの両方をとして計算戦略を設計する方向に進みます。

1
Matthieu M.

ゲームに重点を置いて(投稿で具体的に言及したため)、負荷を分散する方法がいくつかあります。 1つの例は、「スキニング」、つまりモデルのアニメーションです。レンダリングするフレームごとに、アニメーションの各フレームの変換行列を生成し、モデルの頂点に適用して、必要なポーズに変換する必要があります。スムーズな動きを得るために、フレームを補間する必要もあります。 、ただし、アニメーションを元のQuakeのように見せたい(つまり、ぎくしゃくさせない)場合は除きます。

この状況では、CPUで実行して結果をGPUにアップロードしてレンダリングするか、計算とGPUでレンダリングを実行します。今日ではGPUで行われると信じています(「ハードウェアスキニング」として知られています)。何千回も実行する必要がある比較的単純な計算があり、結果から各頂点を同時に計算できるので、そうすることは理にかなっています頂点Aの頂点は、頂点Bの結果には影響しません。

ただし理論的には、GPUとCPUの過負荷に応じて、CPUまたはGPUで動的に切り替えることができます。

ただし、すべての計算にわたってこれを行う主な障害は、CPUとGPUには異なる長所と短所があることです。大規模な並列ジョブはGPUで実行するのが適切ですが、分岐を伴う集中的な線形タスクはCPUで実行するのが適切です。深刻なパフォーマンスに影響を与えることなく、両方で実際に実行できるジョブはほんのわずかです。

全体として、GPUプログラミングの主な問題(少なくともOpenGLとDirectX 11以下では)は、GPUがシェーダーコードを解釈する方法をほとんど制御できないことです。誤って計算間の依存関係を作成すると、GPUはピクセルを1つずつレンダリングし始め、レンダリングされる実際のデータが同一で​​あるにもかかわらず、瞬時に60fpsから10fpsに変わる場合があるため、シェーダー内の分岐は危険です。

0

実際の例の1つは、オープンソース LuxRender レンダリングエンジンで、CPUとGPUを同時に完全にロードすることができます。さらに、複数のGPUを同時にロードしたり、複数のコンピューターに分散したりすることもできます。

LuxRenderは OpenCL を使用してこれを容易にしますが、OpenCLなしのビルドも存在します。

LuxRenderが使用するアルゴリズムは高度に並列化できるため、これは実用的です。 LuxRenderが使用する最も一般的なアルゴリズムは パストレース です。この場合、多くの個別の光路が互いに独立して計算されます。これは、GPUコンピューティングにとって理想的な状況であり、計算ノード間の複雑な同期を必要としない状況です。ただし、GPUの制限(メモリ容量が少ない、一部の複雑なレンダリング機能がサポートされていない、一部のアーティストが一般的に利用できない)により、CPUサポートは依然として不可欠です。

0
PythonNut

はい、それは確かに可能です。

CPUが実行できる計算、GPUも実行できる計算、またはその逆。

しかし、それは珍しいことです。

  • エンジニアリングの複雑さ CPUとGPU(CUDAなど)で同じコードを実行することは可能ですが、プロセッサには異なる機能とパフォーマンス特性があります。 1つはMIMDです。もう1つはSIMDです。一方では高速であるものが他方では低速であるため(分岐など)、パフォーマンスを最大化するために個別のコードを記述する必要があります。

  • コスト効率全体として、GPUはCPUよりもはるかに強力です。 GPUの全体的な考え方は、安価で低速ですが、より多くのプロセッサを使用して、同じコストでCPUよりもはるかに高速に計算を実行することです。 GPUは、1桁または2桁のコスト効率が高くなります。

アルゴリズムをGPUで実行する場合は、それらを最適化し、必要な数だけ追加する方が理にかなっています。

0
Paul Draper