yukarinoki / reseach

0 stars 0 forks source link

GPU First — Execution of Legacy CPU Codes on GPUs #29

Open yukarinoki opened 1 year ago

yukarinoki commented 1 year ago

https://arxiv.org/pdf/2306.11686.pdf

GPUを利用することは、異種システムにおいて高いパフォーマンスを実現するために重要です。しかし、既存のCPUアプリケーションを高速化するためにGPUのフルポテンシャルを引き出すことは、開発者にとって困難な課題となることがあります。移植プロセスでは、高速化可能なコード領域の特定、異なるメモリの管理、ホストとデバイスの実行の同期、デバイス上で直接実行できないライブラリ関数の処理などが必要です。この複雑さにより、専門知識のない人々が効果的にGPUを活用することは難しく、大規模な既存のアプリケーションの一部をオフロードすることさえ困難です。 本論文では、「GPUファースト」と呼ばれる新しいコンパイレーション手法を提案しています。この手法は、アプリケーションソースを修正することなく、既存のCPUアプリケーションを直接GPU向けにコンパイルするものです。アプリケーション内のライブラリ呼び出しは、部分的なlibc GPU実装を介して解決されるか、またはホストへの自動生成されたリモートプロシージャコールを介して処理されます。このアプローチにより、高速化可能なコード領域の特定のタスクが簡素化され、実際のGPUハードウェア上でコード修正の迅速なテストが可能になり、移植作業をガイドすることができます。 OpenMP CPUおよびGPU並列性を持つ2つのHPCプロキシアプリケーション、元々GPUのみの並列性を持つ4つのマイクロベンチマーク、および手動最適化されたOpenMP CPU並列性を備えたSPEC OMP 2012スイートからの3つのベンチマークに対する評価は、ホストアプリケーションをGPUに移植する簡単さを示しています。既存の並列ループに関しては、多くの場合、手動でオフロードされた対応するカーネルと同等のパフォーマンスを実現し、最大14.36倍のGPUでの高速化を達成することができます。これにより、我々のGPUファーストの手法が大規模な既存のアプリケーションの移植作業を効果的にガイドできることが確認されました。

目次

yukarinoki commented 1 year ago

本論文の主な貢献は次の通りですが、限界に関する詳細な説明はセクション4で行います。

yukarinoki commented 1 year ago

OpenMPについて

OpenMP 4.0からTargetが導入された。GPU, FPGAをtargetにして、プログラムを動作させられるようになった。

OpenMPにはTeamsも導入された。独立した初期スレッドを持つチームの集合体。

yukarinoki commented 1 year ago

Tianのやり方で、アプリケーションのソースコードを変更せずにユーザーアプリケーションをGPU向けにコンパイルします。 ただし、我々はコンパイラを2つの異なる方法で拡張

yukarinoki commented 1 year ago

GPUとCPUスレッドの共同はManagedメモリを使用すればできる。多分、pollingする

yukarinoki commented 1 year ago

OpenMPのteams

OpenMPにはteamというものがある。通常(omp for)はteamの中で並列化される。GPUでも同様であるが、これだとGPUの並列性を十分にutilizeすることはできない。そのため、GPU offloadingの部分を複数teamsでの動作に(omp distributed for)に書き換えるようなcompilerを作成した。

すべてのブロックのスレッドを考慮に入れたバージョンでスレッドIDとスレッド数のクエリ呼び出しを置き換えます。どちらの場合も、書き換えにより、すべてのチームおよび各チームのすべてのスレッドの間でワークロードが分散されることを保証します。

すべてのthread_blockの間で同期をとる方法をGPUは提供している。(atomic命令の使用)

初期スレッドがマルチチームカーネルに変換された並列領域に遭遇するたびに、ホストからカーネルを起動するためのRPC呼び出しを発行します。基本的な考え方は、omp parallelをomp teamsに置き換え、その後にomp parallelを続け、並列領域、特にワーク共有部分および同期に適切な変更を加えることです。

最初はメインスレッドのみが実行され、ワーカースレッドは[10]で説明されているように状態マシンで待機し

image

(左側)最初はメインスレッドのみが実行され、ワーカースレッドは[10]で説明されているように状態マシンで待機しています。並列領域が遭遇されると、ワーカースレッドが実行を開始し、メインスレッドは領域が完了するのを待ちます。並列領域が終了すると、メインスレッドはプログラムの逐次部分を再開し、ワーカースレッドは次のタスクを待ちます。

(右側)マルチチーム実行が使用されています。メインカーネルには1つのチームと1つのスレッドしかありません。並列領域が遭遇されると、必要な情報をすべて持って複数のチームで並列カーネルを起動するためのホストRPC呼び出しが発行されます。メインスレッドは、ホストRPCが終了するのを待ってから進行します。この例では、4つのチームが起動され、それぞれに4つのスレッドがあります。これらのチームは別々のエンティティとして取られるのではなく、1つの大きなチームとしてまとめられ、すべてのスレッドが連続したスレッドIDを持つことを保証しています。並列カーネルが完了すると、ホストRPC呼び出しが終了し、メインカーネルのメインスレッドはプログラムの逐次部分の実行を続けます。

yukarinoki commented 1 year ago

Damschenら[5]は、手動でのポーティングや開発者からのヒントを必要とせずに、異種の計算リソースを使用してバイナリアプリケーションを透過的に加速する方法を調査しました。一方、Matsumuraら[14]は、与えられたCソースコード内のステンシルパターンを自動的に変換および最適化し、対応するCUDAコードを生成する自動ステンシルフレームワークを提案しました。これらの研究は主に、ホストプログラムの一部をGPUで実行するための識別および/または生成に焦点を当てています。

Mikushinら[16]は、X86 CPUとNVIDIA GPUの両方のターゲットコードを検出して生成する並列化フレームワークを導入しました。GPU上でネイティブに実行できない関数をサポートするため、彼らはLLVM内の関数呼び出しを、最終的にホストが要求された関数を外部関数インターフェース(FFI)を使用して実行する結果としてインターフェースで置き換えました。しかし、私たちのアプローチは2つの方法で異なります。まず、FFIに頼る代わりに、私たちのコンパイラ変換はホストラッパーを生成し、ホスト上の呼び出しサイトを復元します。次に、彼らのフレームワークでは、GPUのアドレスがホスト上で直接使用され、ホストがアドレスにアクセスしようとするとセグメンテーション違反につながります。セグメンテーション違反のシグナルハンドラーは、GPUのメモリページをCPUのテーブルにマップし、入力データをコピーします。しかし、このメモリ管理サブシステムは、ホストRPCでローカル変数が使用されるような場合、スタック上のメモリバッファに存在する場合には動作しません。Jablinら[11]は、完全に自動化されたCPU-GPU通信を管理および最適化するためのシステムを提案しました。このシステムには、ランタイムライブラリとCPUとGPU間の通信を管理および最適化するために連携して動作するコンパイラ変換のセットが含まれています。他のアプローチとは異なり、このシステムは静的なコンパイル時の分析の強さやプログラマー提供の注釈に依存していません。私たちのポインタ引数分析は、彼らの作業に似た設計を共有しています。

Tianら[26]は、ホストプログラム全体をGPU上で実行しようとした最初の試みでした。彼らは、OpenMPターゲットオフロードを使用して、ホストアプリケーションのコンパイルと実行の移植性を活用することを提案しました。しかし、彼らのアプローチでは、アプリケーション開発者がホストとデバイスの両方でラッパー関数を提供する必要があり、手動またはスクリプトを介して行う必要があります。彼らはまた、可変長の関数をサポートしておらず、彼らの論文は、単一チームの実行制限による深刻なパフォーマンスの後退を示しています。