2017-08-17 7 views
4

でパフォーマンスをカットしますなぜ私がこの記事を読んで:(GPUのコードで)「のif-else」文は半分

FPGA or GPU? - The evolution continues

を誰かが彼が書いているコメントを追加しました:

GPUはSIMDなので、 "if-else"ステートメントのコードでは、 のパフォーマンスが半減します。コアの半分が ステートメントのif部分を実行し、残りの半分のコアがアイドル状態のまま残り、 コアの最初の半分がアイドル状態のままelse計算が実行されます。

なぜわかりませんか?

if-elseを使用するとGPU(つまりOpenCL)を使用する理由は、パフォーマンスが半減するのですか?

+0

GPUの設計は本質的に分岐操作を好まないので、コードをこの特性に適合させることを検討する必要があります。 – tibetty

答えて

10

一般的な分岐はパフォーマンスに影響しませんが、分岐はの相違です。つまり、2つのスレッドが異なるパスを使用しています(たとえば、1つが条件を満たしていて、もう1つは条件を満たしていません)。 GPUのすべてのスレッドが同じ「コード行」を実行するため、パスの一部ではないコードが実行されている間にスレッドが待機する必要があります。
1つのワープ(NVIDIA)または波面(AMD)のすべてのスレッドのみが同じ「コード行」を実行するので、実際にはそうではありません。 (現在、NVIDIA GPUのワープサイズは32、AMD GPUの最大サイズは64です。)

カーネルにif-elseブロックがあると、最悪の場合のシナリオは実際には50%の性能低下です。さらに悪いことに、n分岐がある場合、パフォーマンスは分岐なしのパフォーマンスの1/nに減少する可能性があります(分岐がないか、ワープ/ウェイフエンドのすべてのスレッドが同じパスを使用しています)。もちろん、このようなシナリオでは、カーネル全体をif-else(またはswitch)の構造体に埋め込む必要があります。

しかし、これは、異なるパスを取っているスレッドが同じワープ/ワーフフェンスにある場合にのみ発生します。できるだけ分岐の発散を避けるために、コードを書いたり、データを並べ替えたり、アルゴリズムを選択したりするのはあなた次第です。

Tl; DR:ブランチが存在する可能性がありますが、異なるスレッドが異なるブランチを使用している場合は、分岐とそれに伴うパフォーマンスの低下を避けるために、異なるワープ/ウェファフロントでなければなりません。

+0

ほとんどの場合、人々は発散について読むとすぐにGPU上のブランチを恐れています。しかし、ほとんどの場合、カーネルはピーク時の性能に近くないところで実行されていますが、メモリ帯域幅、共有メモリ、または使用可能なワープの欠如によってスループットが制限されています。その後、発散はパフォーマンスにごくわずかな影響しか与えません。 –

+0

@JanLucas:ピークパフォーマンスはほとんど達成されませんが、ブランチの相違がそれをさらに悪化させることは間違いありません。もちろん、ピークパフォーマンスの近くで動作するカーネルのパフォーマンスを二分すると、パフォーマンスの損失は大きくなりますが、絶対的な数値だけではなく、相対的な数値になります。私が思うには、発散について心配しない方が良いと思うのは、カーネルの小さな部分だけで分岐が頻繁に分岐することです(例えば、わずか10%が発散の影響を受け、 。 – Shadow

+0

@JanLucas:それはしばしば、発散について考えることは決して悪いことではありません。なぜなら、それはしばしば、不一致のメモリアクセスにつながる悪いデータレイアウトと、それで貴重なメモリ帯域幅の浪費につながります。 – Shadow

関連する問題