コンピュートクロスベンダーグラフィックカード(AMD、Qualcomm、Nvidia&Friends)のGeneral目的GPUコンピューテフレームワーク) |
Discord&Community Callsに参加しますか?ドキュメントブログ投稿⌨例?
以下に、C ++およびPython Komputeインターフェイスを使用したGPU乗算の例を見つけることができます。
質問 /ディスカッションのために不一致に参加したり、GitHubの問題を開いたり、ドキュメントを読んだりできます。
C ++インターフェイスは、Komputeのネイティブコンポーネントへの低レベルのアクセスを提供し、高度な最適化とコンポーネントの拡張を可能にします。
void kompute ( const std::string& shader) {
// 1. Create Kompute Manager with default settings (device 0, first queue and no extensions)
kp::Manager mgr;
// 2. Create and initialise Kompute Tensors through manager
// Default tensor constructor simplifies creation of float values
auto tensorInA = mgr. tensor ({ 2 ., 2 ., 2 . });
auto tensorInB = mgr. tensor ({ 1 ., 2 ., 3 . });
// Explicit type constructor supports uint32, int32, double, float and bool
auto tensorOutA = mgr. tensorT < uint32_t >({ 0 , 0 , 0 });
auto tensorOutB = mgr. tensorT < uint32_t >({ 0 , 0 , 0 });
std::vector<std::shared_ptr<kp::Memory>> params = {tensorInA, tensorInB, tensorOutA, tensorOutB};
// 3. Create algorithm based on shader (supports buffers & push/spec constants)
kp::Workgroup workgroup ({ 3 , 1 , 1 });
std::vector< float > specConsts ({ 2 });
std::vector< float > pushConstsA ({ 2.0 });
std::vector< float > pushConstsB ({ 3.0 });
auto algorithm = mgr. algorithm (params,
// See documentation shader section for compileSource
compileSource (shader),
workgroup,
specConsts,
pushConstsA);
// 4. Run operation synchronously using sequence
mgr. sequence ()
-> record <kp::OpSyncDevice>(params)
-> record <kp::OpAlgoDispatch>(algorithm) // Binds default push consts
-> eval () // Evaluates the two recorded operations
-> record <kp::OpAlgoDispatch>(algorithm, pushConstsB) // Overrides push consts
-> eval (); // Evaluates only last recorded operation
// 5. Sync results from the GPU asynchronously
auto sq = mgr. sequence ();
sq-> evalAsync <kp::OpSyncLocal>(params);
// ... Do other work asynchronously whilst GPU finishes
sq-> evalAwait ();
// Prints the first output which is: { 4, 8, 12 }
for ( const float & elem : tensorOutA-> vector ()) std::cout << elem << " " ;
// Prints the second output which is: { 10, 10, 10 }
for ( const float & elem : tensorOutB-> vector ()) std::cout << elem << " " ;
} // Manages / releases all CPU and GPU memory resources
int main () {
// Define a raw string shader (or use the Kompute tools to compile to SPIRV / C++ header
// files). This shader shows some of the main components including constants, buffers, etc
std::string shader = ( R"(
#version 450
layout (local_size_x = 1) in;
// The input tensors bind index is relative to index in parameter passed
layout(set = 0, binding = 0) buffer buf_in_a { float in_a[]; };
layout(set = 0, binding = 1) buffer buf_in_b { float in_b[]; };
layout(set = 0, binding = 2) buffer buf_out_a { uint out_a[]; };
layout(set = 0, binding = 3) buffer buf_out_b { uint out_b[]; };
// Kompute supports push constants updated on dispatch
layout(push_constant) uniform PushConstants {
float val;
} push_const;
// Kompute also supports spec constants on initalization
layout(constant_id = 0) const float const_one = 0;
void main() {
uint index = gl_GlobalInvocationID.x;
out_a[index] += uint( in_a[index] * in_b[index] );
out_b[index] += uint( const_one * push_const.val );
}
)" );
// Run the function declared above with our raw string shader
kompute (shader);
}
Pythonパッケージは、高性能と高速開発ワークフローを確保しながら、実験を可能にする高レベルのインタラクティブなインターフェイスを提供します。
from . utils import compile_source # using util function from python/test/utils
def kompute ( shader ):
# 1. Create Kompute Manager with default settings (device 0, first queue and no extensions)
mgr = kp . Manager ()
# 2. Create and initialise Kompute Tensors through manager
# Default tensor constructor simplifies creation of float values
tensor_in_a = mgr . tensor ([ 2 , 2 , 2 ])
tensor_in_b = mgr . tensor ([ 1 , 2 , 3 ])
# Explicit type constructor supports uint32, int32, double, float and bool
tensor_out_a = mgr . tensor_t ( np . array ([ 0 , 0 , 0 ], dtype = np . uint32 ))
tensor_out_b = mgr . tensor_t ( np . array ([ 0 , 0 , 0 ], dtype = np . uint32 ))
assert ( t_data . data_type () == kp . DataTypes . uint )
params = [ tensor_in_a , tensor_in_b , tensor_out_a , tensor_out_b ]
# 3. Create algorithm based on shader (supports buffers & push/spec constants)
workgroup = ( 3 , 1 , 1 )
spec_consts = [ 2 ]
push_consts_a = [ 2 ]
push_consts_b = [ 3 ]
# See documentation shader section for compile_source
spirv = compile_source ( shader )
algo = mgr . algorithm ( params , spirv , workgroup , spec_consts , push_consts_a )
# 4. Run operation synchronously using sequence
( mgr . sequence ()
. record ( kp . OpTensorSyncDevice ( params ))
. record ( kp . OpAlgoDispatch ( algo )) # Binds default push consts provided
. eval () # evaluates the two recorded ops
. record ( kp . OpAlgoDispatch ( algo , push_consts_b )) # Overrides push consts
. eval ()) # evaluates only the last recorded op
# 5. Sync results from the GPU asynchronously
sq = mgr . sequence ()
sq . eval_async ( kp . OpTensorSyncLocal ( params ))
# ... Do other work asynchronously whilst GPU finishes
sq . eval_await ()
# Prints the first output which is: { 4, 8, 12 }
print ( tensor_out_a )
# Prints the first output which is: { 10, 10, 10 }
print ( tensor_out_b )
if __name__ == "__main__" :
# Define a raw string shader (or use the Kompute tools to compile to SPIRV / C++ header
# files). This shader shows some of the main components including constants, buffers, etc
shader = """
#version 450
layout (local_size_x = 1) in;
// The input tensors bind index is relative to index in parameter passed
layout(set = 0, binding = 0) buffer buf_in_a { float in_a[]; };
layout(set = 0, binding = 1) buffer buf_in_b { float in_b[]; };
layout(set = 0, binding = 2) buffer buf_out_a { uint out_a[]; };
layout(set = 0, binding = 3) buffer buf_out_b { uint out_b[]; };
// Kompute supports push constants updated on dispatch
layout(push_constant) uniform PushConstants {
float val;
} push_const;
// Kompute also supports spec constants on initalization
layout(constant_id = 0) const float const_one = 0;
void main() {
uint index = gl_GlobalInvocationID.x;
out_a[index] += uint( in_a[index] * in_b[index] );
out_b[index] += uint( const_one * push_const.val );
}
"""
kompute ( shader )無料のGPUを使用できるインタラクティブコラブノートブックを試してみることができます。利用可能な例は、以下のPythonおよびC ++の例です。
ブログ投稿からインタラクティブなC ++コラブをお試しください | ブログ投稿からインタラクティブなPython Colabをお試しください |
また、FOSDEM 2021 Conferenceで発表された2つの次の講演を確認することもできます。
どちらのビデオにもタイムスタンプがあり、最も関連性の高いセクションにスキップできるようになります。両方のイントロと動機はほぼ同じであるため、より具体的なコンテンツにスキップできます。
C ++愛好家向けのビデオをご覧ください | Python&Machine Learning愛好家のビデオをご覧ください |
Komputeのコアアーキテクチャには、次のものが含まれています。
完全な内訳を確認するには、C ++クラスの参照をさらに読むことができます。
| 完全なアーキテクチャ | 簡略化されたコンピュートコンポーネント |
|---|---|
(非常に小さい、詳細についてはドキュメントの完全な参照図を確認してください) |
Komputeは、VK :: Fencesを介してAsynrChonousの方法で操作を実行する柔軟性を提供します。さらに、Komputeはキューの明示的な割り当てを可能にします。これにより、キューファミリ全体で操作を並行して実行できます。
以下の画像は、Komputeシーケンスをさまざまなキューに割り当てて、ハードウェアに基づいて並列実行を可能にする方法に関する直感を示しています。例として、例としてNVIDIA 1650を使用してどのように機能するかを説明する詳細なドキュメントページを見ることができます。
Komputeは、モバイル環境で動作するように最適化されています。ビルドシステムにより、Android環境向けのVulkan共有ライブラリの動的荷重と、CPPヘッダー用のAndroid NDKラッパーが機能します。
完全なダイビングについては、ブログ投稿「モバイルアプリをオンデバイスGPU加速機械学習でスーパーチャージング」することを読むことができます。 また、Android Studioを使用して実行できるリポジトリ内のエンドツーエンドの例コードにアクセスすることもできます。 |
C ++コアSDKに加えて、KomputeのPythonパッケージを使用して、同じコア機能を公開し、リスト、NumpyアレイなどのPythonオブジェクトとの相互運用性をサポートすることもできます。
唯一の依存関係は、Python 3.5+およびCmake 3.4.1+です。次のコマンドを使用して、Python PypiパッケージからKomputeをインストールできます。
pip install kp
Master Branchから以下をインストールすることもできます。
pip install git+git://github.com/KomputeProject/kompute.git@master
詳細については、PythonパッケージのドキュメントまたはPythonクラスの参照ドキュメントをお読みください。
提供されたビルドシステムは、 cmakeを使用して、クロスプラットフォームビルドを可能にします。
トップレベルのMakefile 、開発のための最適化された構成のセットとDocker Image Buildを提供しますが、次のコマンドでビルドを開始できます。
cmake -Bbuild
また、 add_subdirectory -androidの例Cmakelists.txtファイルを使用して、レポでKomputeを追加することもできます。これがどのように行われるかを示します。
ビルド構成のより高度な概要については、ビルドシステムディープダイブドキュメントをご覧ください。
PRと問題に感謝します。貢献したい場合は、「最初の問題」タグをチェックしてみてください。しかし、Komputeや報告の問題を使用しても大きな貢献です!
デバッグレイヤーを使用して実行したい場合は、 KOMPUTE_ENV_DEBUG_LAYERSパラメーターでそれらを追加できます。
export KOMPUTE_ENV_DEBUG_LAYERS="VK_LAYER_LUNARG_api_dump"
ドキュメントを更新するには、次のことが必要です。
make push_docs_to_ghpagesでgithubページにプッシュしますユニットテストの実行は、貢献者にとって大幅に簡素化されています。
テストはCPUで実行され、ACTコマンドラインインターフェイス(https://github.com/nektos/act)を使用してトリガーできます。コマンドライン(およびDockerデーモンを起動する)をインストールしたら、次のように入力する必要があります。
$ act
[Python Tests/python-tests] Start image=axsauze/kompute-builder:0.2
[C++ Tests/cpp-tests ] Start image=axsauze/kompute-builder:0.2
[C++ Tests/cpp-tests ] ? docker run image=axsauze/kompute-builder:0.2 entrypoint=["/usr/bin/tail" "-f" "/dev/null"] cmd=[]
[Python Tests/python-tests] ? docker run image=axsauze/kompute-builder:0.2 entrypoint=["/usr/bin/tail" "-f" "/dev/null"] cmd=[]
...
リポジトリには、C ++およびPythonコードのユニットテストが含まれており、 test/およびpython/testフォルダーの下にあります。
テストは現在、GitHubアクションを使用してCIを介して実行されます。 docker-builders/にある画像を使用します。
ハードウェアの要件を最小限に抑えるために、Swiftshaderを使用してCPUで直接GPUなしで実行できます。
CIとテストのセットアップ方法の詳細については、ドキュメントのCI、Docker、テストセクションにアクセスできます。
このプロジェクトは、Pytorch、Tensorflow、Alibaba DNN、Tencent NCNNなどの多くの新しく有名なML&DLプロジェクトが、とりわけ、Vulkan SDKを統合または統合してモバイル(およびクロスベンダー)GPUサポートを統合しようとしていることを確認した後に始まりました。
Vulkan SDKは、高度に専門化された最適化を可能にする優れた低レベルのインターフェイスを提供しますが、アプリケーションコードの作成を開始するために500〜2000行のコードを必要とする非常に冗長コードのコストがあります。これにより、これらの各プロジェクトは、Vulkan SDKの非計算関連機能を抽象化するために同じベースラインを実装する必要があります。この大量の標準化されていないボイラープレートは、限られた知識移転、独自のフレームワークの実装バグが導入される可能性が高くなる可能性があります。
現在、Vulkan SDKインターフェイスを隠さないようにKomputeを開発しています(非常によく設計されています)が、Vulkan SDKのGPUコンピューティング機能に直接焦点を合わせて増強しています。この記事では、Kpuの動機の高レベルの概要と、GPUコンピューティングとコアKomputeアーキテクチャの両方を紹介する一連の実例を説明します。