3

OK、そう: 私は最初の動作中のHalide ジェネレーターを私の小さな画像処理プロジェクトのcmake ビルド システムに統合することに成功しました。

ジェネレーターは、Halide コードベースのサンプル コードに基づいて、画像のサイズ変更およびリサンプリング アルゴリズムを実装しHalide/apps/resize/resize.cppます。でHalideGenerator.cmake、Halide プロジェクトが独自のビルド スクリプトで行うように。

これまでのところ、これはすべてうまく機能していますが、コード生成のニュアンスの領域では、私のドメインの専門知識が不足しています。たとえば、スケジューリング方法を微調整して、ラップトップで観測された最高の経験的速度を得まし。コード生成プロセスの理解。

具体的には、これにアプローチする方法がわかりません。デフォルトを使用するか、ターゲット プラットフォームの特定のオプションをオンにするのが最善ですか? 後者の場合、どこかに条件付きコードを含める必要がありますか、それともバイナリにフォールバックを含めることができますか?

私が話していることは次のとおりです。Halide チュートリアル レッスン #15 のソースには、さまざまなオプションでジェネレーターを呼び出す複雑なスクリプトがあります。このスクリプトのコード コメントのスニペットを次に示します。

# If you're compiling and linking multiple Halide pipelines, then the
# multiple copies of the runtime should combine into a single copy
# (via weak linkage). If you're compiling and linking for multiple
# different targets (e.g. avx and non-avx), then the runtimes might be
# different, and you can't control which copy of the runtime the
# linker selects.

# You can control this behavior explicitly by compiling your pipelines
# with the no_runtime target flag. Let's generate and link several
# different versions of the first pipeline for different x86 variants: [snip]

…このことから、何をしなければならないか、何をすべきか、または何すべきかを裁量的に区別することは困難です。比較すると、C++ または Objective-C プロジェクト (さらに多くのビザンチンの例) をセットアップするときにこれらの問題に対処する必要はありません。これは、コンパイラとリンカーがこれらの決定のほとんどを行い、多くても 1 つまたは 2 つのフラグが必要なためです。

私の質問は、Halide ジェネレーターの出力ライブラリ バイナリを既存のプロジェクトに統合するにはどうすればよいかということです。移植性をさらに制限することなく(例: GPU、SSE2/3、AVX2 などを使用)、ジェネレーターの出力を可能な限り高速にします少し違うマシンで不思議なことにセグメンテーションフォールトですか?

具体的には、私のプロセスはどのようなものであるべきですか? たとえば、最初は最小公分母のみを対象とし、その後、よりエキゾチックなプロセッサ機能を段階的に活用する必要がありますか?


編集: 以下のコメントで述べたように、これは、stdoutオプションなしで呼び出されたときに GenGen バイナリが出力するものです。

イムグル

4

2 に答える 2

2

最近の時点で、AOT コンパイルは、ランタイム検出による複数の CPU 機能のカスタマイズの生成をサポートするようになりました。ターゲットのコンマ区切りリストと static_library を出力として GenGen を使用するだけです。

GenGen -e static_library,h target=x86-64-linux-sse41-avx,x86-64-linux-sse41,x86-64-linux

これにより、以下を含む .a ファイルが生成されます。

  • AVX+SSE4.1、SSE4.1、plain-old-x86-64 に特化してコンパイルされた 3 つのバージョンのコード
  • ハライド _can_use_target_features() ランタイム コールを使用して、実際のターゲット マシンに適したものを選択するシン ラッパー

詳細については、Func::compile_to_multitarget_static_library() および multitarget_generator.cpp/multitarget_aottest.cpp を参照してください。

于 2016-08-01T16:59:10.157 に答える
1

バイナリ (AOT) を事前に生成する場合、ランタイム ディスパッチが必要なようです。プログラムは、起動時に CPU/GPU 環境を調べて、使用する機能 (AVX、OpenCL など) を決定します。これはハライド特有のものではありません。

  • ターゲットとする高度な機能のセット (高性能デスクトップ GPU) を最良のケースとして選択し、すべてのマシンで動作する最小限の機能のセット (SSE2 のみ) を選択します。
  • パフォーマンスを必要とするすべての関数を含むこれらの機能セットごとに DLL/dylib/so をビルドします。これらは別の方法でスケジュールすることも、まったく異なるFunc定義で構築することもできます。両方のセットを同じソース コード ファイルに格納しTarget、生成時にオブジェクトをテストしてどちらかを選択できます。
  • プログラムの起動時に、最適な機能が存在するかどうかを確認し、存在する場合はそのライブラリをロードして使用します。不足している機能がある場合は、デフォルトで最も互換性のあるバージョンを使用してください。

サポートする機能セットとライブラリの数を自由に選択できます。

もう 1 つの方法は、プログラムの起動時に Halide コードをコンパイルすることです (JIT)。Targetによって返されるオブジェクトを使用することをお勧めしますget_jit_target_from_environment()。これは、環境変数の内容を使用するHL_JIT_TARGETか、その変数が設定されていない場合は「ホスト」を使用します。「ホスト」ターゲット文字列は と同じでget_host_target()、Halide が CPU/GPU 環境を調べて、見つかった機能を設定することを意味します。その後、オブジェクトを動的にテストし、TargetGPU または CPU スケジューリングを使用できます。

于 2016-08-01T16:36:55.643 に答える