アクセラレータの非同期ホスト制御 - 2023.2 日本語

Vitis 統合ソフトウェア プラットフォームの資料: アプリケーション アクセラレーション開発 (UG1393)

Document ID
UG1393
Release Date
2023-12-13
Version
2023.2 日本語

VSC モードでは、ハードウェアの構築 で説明するように、ユーザー定義のハードウェア パイプラインを含む CU を使用してアクセラレータをコンパイルできます。このようなパイプラインは、AXI4-Stream を介して相互接続される PE で構成され、グローバル メモリやイーサネット QSFP ポートなどの IO インターフェイスなど、AXI4 接続のプラットフォーム ポートにも接続できます。プラットフォームでは、このようなインターフェイスをユーザー定義パイプラインの PE に接続できる AXI4-Stream ポートに変換する IP が提供されます。

VSC を使用すると、このようなハードウェア パイプラインが、ホスト CPU で実行されているアプリケーションから実行時の処理動作をダイナミックに変更できるように簡単に設定できます。このようなアクセラレータを作成する方法は、次のとおりです。システム構成の例を次の図に示します。

図 1. アクセラレータのインプリメンテーション

Eth_Rx および Eth_Tx モジュールは、通常、AXI4-Stream ワードをイーサネット パケットに変換するプラットフォーム IP です。これらは、ユーザー定義の AXI4 インターフェイスを使用したカスタム IP にすることもできます。

白いボックスに示されている残りのアクセラレータ パイプラインは、AXI4-Stream 接続を使用して VSC で作成されます。パイプライン内の PE は、インターネット プロトコル パケット フィルターのようなパケット プロセッシングなどの、ユーザー定義の機能です。この例には、2 つのタスク (modsmp という PE) を使用して作成されたパイプラインがあります。また、このシステムは、これらのパイプライン PE への AXI4-Stream 接続を持つ別の制御 PE で構成されます。次は、アクセラレータ コードの例です。左側は .hpp ファイル、右側は .cpp ファイルです。

// -- file: ETH.hpp --
#include "vpp_acc.hpp"
class ETH : public VPP_ACC<ETH,1>
{
public:
    ZERO_COPY(dIn);
    ZERO_COPY(dOut);

    SYS_PORT(dIn,  MEM_BANK0);
    SYS_PORT(dOut, MEM_BANK1);

    FREE_RUNNING(fsk_mod);
    FREE_RUNNING(fsk_smp);
    FREE_RUNNING(eth_rx);
    FREE_RUNNING(eth_tx);
    
    static void compute(int cmd, Pkt* dIn, Pkt* dOut);

    static void control(...
    static void fsk_mod(...
    static void fsk_smp(...
    static void eth_tx(...
    static void eth_rx(...
};
// -- file: ETH.cpp --
void ETH::compute(int cmd, Pkt* dIn, Pkt* dOut)
{
    static IntStream dropS("drop");
    static IntStream addS("add");
    static IntStream reqS("req");
    static PktStream smpS("smp");
    static BitStream getS("get");
    static IntStream sntS("snt");
    static PktStream Ax("Ax", /*post_check=*/false);
    static PktStream Bx("Bx", /*post_check=*/false);
    static PktStream Cx("Cx", /*post_check=*/false);
    
    control(cmd, dIn, dOut,
            dropS, addS, reqS, smpS, getS, sntS);
    eth_rx (Ax);
    fsk_mod(Ax, Bx, dropS, addS);
    fsk_smp(Bx, Cx, reqS, smpS);
    eth_tx (Cx, getS, sntS);
}

この例では、eth_tx および eth_rx などを含む 5 つの PE が定義されており、プラットフォーム IP が AXI4-Stream でワードを送受信する動作が模倣されます。compute() スコープは、これらの PE 間の AXI4-Stream 接続を使用してアクセラレータ パイプラインをインプリメントします。control PE はこれらのストリームでコマンド ワードを送信でき、タスク PE (fsk_mod および fsk_smp) はこれらのコマンドを AXI4-Stream を介して監視し、ビヘイビアーを変更することで反応します。fsk_smp PE は、要求された数のパケットを control PE にサンプリングして戻すことで反応します。fsk_mod PE は、パケット データに値を追加するか、Eth_Rx から Eth_Tx に渡されるパケットをドロップすることによって反応します。

パイプライン PE (fsk_mod および fsk_smp) は、入力ストリーム内のワードによって動作に駆動される終了しない PE なので、FREE_RUNNING です (ガイダンス マクロ を参照)。

control PE は、入力 (dIn) および出力 (dOut) のインターフェイス引数データ ポインターの 2 つの SYS_PORT 接続、およびスカラー コマンド引数 (cmd) を介してホスト CPU と通信します。control PE はフリーランニングではなく、ホスト CPU からの compute() 呼び出しに反応します。このシステム構成は、コマンドの性質および対応する PE 機能を含め、すべてユーザーが定義します。

次は、ホスト コードのスナップショットです。例全体は、GitHub を参照してください。

// -- file: host.cpp --
#include "vpp_acc_core.hpp" // required
#include "ETH.hpp"
int config_sample(int sz)
{
    printf("main: sample %d\n", sz);

    Pkt* sample  = (Pkt*)ETH::alloc_buf(sz * sizeof(Pkt), vpp::output);
    Pkt* config  = (Pkt*)ETH::alloc_buf(sizeof(Pkt), vpp::input);
    config[0].dt = sz;

    auto fut = ETH::compute_async(cmd_sample, config, sample);
    fut.get();
    print_sample(sample, sz);
    int pkt_nr = sample[0].nr;
    ETH::free_buf(config);
    ETH::free_buf(sample);
    return pkt_nr;
}

VSC ホスト コードによって発行されるジョブ コマンドは、特に compute_async() API を使用した場合、制御 PE をイネーブルにしてコマンドを変換し、コマンド ストリームを介してコンフィギュレーション ワードをパイプライン PE に渡すことができます。このスナップショットには、パケット サンプリング コマンドを発行するユーザー定義の API が表示されます。必要な szsample バッファーが実行時に割り当てられ、compute_async() 呼び出しがパケットの sz 数を取り込むように制御 PE をトリガーし、ワードをホストに戻します。compute() によって返された fut は、結果が使用可能になるまでホスト コードでブロックされます。ただし、compute_async() は名前の示すとおり非同期呼び出しで、アクセラレータをトリガーします。サンプル ワードが返され、ホストによって処理されると、対応するバッファーがフリーになります。

この場合、ホスト制御は計算ジョブの連続パイプラインではありませんが、不定期でタイミングが重要ではないジョブだけなので、send_while/receive_all スレッドはこれを管理しません。代わりに、vpp_acc_core.hpp で定義された compute_async() API を使用して同期がアプリケーションで管理されます。

重要: この vpp_acc_core.hpp ヘッダー ファイルは、ホスト コード ファイルにのみ、vpp_acc.hpp が含まれる前に含める必要があります。

VSC では、このようなハードウェア パイプラインを構成し、ホスト CPU から非同期に制御できます。このようなアクセラレータのアプリケーションの 1 つは、NIC カード上のパケット プロセッシング アクセラレータです。たとえば、X3 ハイブリッド プラットフォームでは、MAC インターフェイスを介して、QSFP ポートに到着するイーサネット パケットを AXI4-Stream に変換するイーサネット伝送および受信 IP が提供されます。さらに、NIC インターフェイスを使用すると、アクセラレータが PCIe を介して接続されたホスト CPU にデータを提供できます。または、PCIe を介してホスト CPU メモリへの直接アクセスにホスト メモリ アクセスを使用できます 。VSC を使用すると、アクセラレータ パケット プロセッシング パイプラインを PL 上で構成し、PCIe を介して CPU によって非同期的に制御できます。