バッファー オーバーフローを回避するための信号サイズの設定 - 2021.2 日本語

Vitis Model Composer ユーザー ガイド (UG1483)

Document ID
UG1483
Release Date
2021-10-22
Version
2021.2 日本語

AI エンジン インポート ブロック マスクの Signal Size フィールドは、ストリーム出力またはカスケード出力を持つカーネルにのみ適用されます。インプリメンテーションでは重要ではなく、Simulink 環境でのシミュレーションでのみ意味があります。このセクションでは、信号サイズとその設定方法について詳しく説明します。

まず、ウィンドウ入力とストリーム出力を持つ非常に単純なカーネルを考えてみます。カーネル コードは次のとおりです。

void win_in_stream_out(input_window_int16 * in1,output_stream_int32 * out) {
  int16 val;
  for (unsigned i=0; i<16; i++) {
    window_readincr(in1,val);
    int32 squaring = val * val;
    writeincr(out,squaring);
  }
}
図 1. AIE カーネル: ウィンドウ入力/ストリーム出力

このカーネルは、呼び出しごとにサイズ 16 のウィンドウを受信し、16 個の出力サンプルを生成します。このカーネルを、AIE Kernel ブロックを使用してインポートします。次の図に、このブロックのマスクを示します。

図 2. [Block Parameters] ダイアログ ボックス: window_in_stream_out

信号サイズをどの値に設定しても、出力値には影響しません。この例では、カーネルの呼び出しごとに 16 個のサンプルが生成されるので、信号サイズを 16 に設定します。この場合、このブロックの出力は最大サイズ 16 (信号サイズと同じ) の可変サイズ信号となり、各出力には 16 個のサンプルが含まれます。信号サイズを 32 に設定すると、ブロックの出力は最大サイズ 32 の可変サイズ信号になりますが、各出力には 16 個のサンプルしか含まれません。

信号サイズを 16 未満の値 (8 など) に設定すると、どうなるでしょうか。この場合、出力は最大サイズ 8 の可変サイズ信号になります。前述のように、カーネルの呼び出しごとに 16 個のサンプルが生成されます。これらのサンプルの 8 個がブロックから出力されます。残りの 8 個のサンプルは、ブロックの内部バッファーに格納されます。カーネルの呼び出し回数が多くなると、ブロックの内部バッファーがフルになり、次の図に示すようなバッファー オーバーフロー エラーが表示されます。

図 3. バッファー オーバーフロー エラー

この例は単純すぎるかもしれません。信号サイズを 16 未満に設定する理由は特にないでしょう。次に、2 つの AI エンジン カーネルを含むモデルを考えてみます。先ほど作成したカーネルの出力を、ウィンドウ入力とウィンドウ出力を持つ別の AI エンジン カーネルに接続します。2 番目のカーネルのコードは、次のとおりです。

void win_in_win_out(input_window_int16 * inw, output_window_int16 * outw)
{
    int16 temp;
    for (unsigned i=0; i<8; i++) {
        window_readincr(inw,temp);
        window_writeincr(outw,temp);
    }
}
図 4. 2 つの AIE Kernel ブロック

このカーネルは、サイズ 8 の入力ウィンドウを必要とし、サイズ 8 のウィンドウを生成します。次の 2 つの状況を考えます。1 つ目の状況では、最初のブロックの信号サイズが 16 に設定されています。前述のように、信号サイズが 16 の場合、最初のブロックのバッファーはオーバーフローしません。ここで、2 番目のブロックをより詳細に見てみます。2 番目のカーネルは、16 個のサンプルを受信した後、2 回呼び出されます。各呼び出しで 8 つのサンプルが生成され、合計 16 個のサンプルが生成されます。出力ウィンドウ サイズは 8 なので、ブロックは 8 個のサンプルを出力し、残りの 8 個を内部バッファーに格納します。前述の場合と同様に、このモデルを長時間実行すると、2 番目のブロックのバッファーがオーバーフローし、シミュレーションが停止します。

2 つ目の状況では、オーバーフローを回避するため、最初のブロックの信号サイズを 8 に設定します。これにより、2 番目のブロックでオーバーフローが発生するのを回避できます。ただし、先ほど説明したように、今度は最初のブロックのバッファーがオーバーフローします。この状況を解決するにはどうすればよいでしょうか。

バッファー オーバーフローは、ブロックが処理できる量よりも多くのデータをブロックに供給するために発生します。レートを下げると、カーネルでバッファー内の過剰なデータを処理できるようになり、オーバーフローを回避できます。これを詳しく見てみましょう。

シミュレーションがしばらく実行されており、最初のブロックのバッファーが空ではないとします。最初のブロックへのデータ供給を停止すると、入力データがないので、Simulink が最初のブロックを呼び出すたびにはカーネルは呼び出されませんが、バッファーにはサンプルがあるので、バッファーが空になるまでブロックはサンプルを 8 個ずつ生成し続け、その後空の可変サイズ信号を生成します。

この情報は、バッファー オーバーフローを回避するのに役立ちます。入力を停止する代わりに、最初のブロックへのデータのフローを削減します。これには、Engine/Tools の To Variable Size ブロックを使用し、ブロック マスクの出力サイズを入力のサイズより小さくするのが 1 つの方法です。次の図は、このデザインの入力に変数に To Variable Size ブロックを追加したものです。

図 5. 2 つの AIE Kernel ブロック: バッファー ブロック入力

このデザインでは、ブロックの各呼び出しで最初のブロックに供給されるサンプル数が少ないため、バッファーはオーバーフローしません。このモデルでは、バッファー ブロックはステップ 0 時に 0 サンプルを生成するので、出力はバッファー ブロックがないモデルとは異なります。

ヒント: ストリーム出力を持つブロックがウィンドウ入力を持つブロックに接続されている場合は、生成ブロックの信号サイズを消費ブロックの入力ウィンドウと同じサイズに設定します。
ヒント: バッファー オーバーフローを回避するには、バッファー ブロックを使用してデータをシステムに供給するレートを下げます。