標準垂直たたみ込み

次の段階では、次の図に示す垂直たたみ込みを実行します。



垂直たたみ込みのプロセスは、水平たたみ込みと似ています。たたみ込み係数 (この場合は Vcoeff) を使用したたたみ込みには、K 個のデータ サンプルが必要です。垂直方向の最初の K 個のサンプルを使用して最初の出力が作成された後、次の K 個の値を使用して 2 つ目の出力が作成されます。この処理は、最後の出力が作成されるまで各列に対して実行されます。

水平および垂直の境界効果により、垂直たたみ込み後の画像はソース画像 src よりも小さくなります。

これらの処理を実行するコードは、次のとおりです。

Clear_Dst:for(int i = 0; i < height * width; i++){
  dst[i]=0;
}
// Vertical convolution
VconvH:for(int col = border_width; col < height - border_width; col++){
  VconvW:for(int row = 0; row < width; row++){
    int pixel = col * width + row;
    Vconv:for(int i = - border_width; i <= border_width; i++){
      int offset = i * width;
      dst[pixel] += local[pixel + offset] * vcoeff[i + border_width];
    }
  }
}

このコードには、水平たたみ込みコードを使用して既に説明した問題と同様の問題があります。

  • 出力画像 dst の値 を 0 に設定するのに、多数のクロック サイクルが費やされます。この場合、1920*1080 画像サイズに対してさらに約 2 百万サイクル必要です。
  • local 配列に格納されたデータを再度読み出すために、各ピクセルが複数回アクセスされます。
  • 出力配列/ポート dst に対しても、各ピクセルが複数回書き込まれます。

上記のコードのアクセス パターンでは、大型の local 配列が必要となります。アルゴリズムでは、最初の計算を実行するために行 K のデータが使用可能になっていることが必要です。次の列に進む前に各行のデータを処理するため、画像全体がローカルに格納されている必要があります。そのためすべての値が格納されるので、FPGA に大型のローカル ストレージが作成されます。

さらに、local 配列からデータがストリーミング出力されないので、コンパイラ指示子を使用してハードウェア関数のパフォーマンスを最適化する段階に達したときに、水平および垂直ループ間のデータのフローを FIFO (高パフォーマンスで低リソースのユニット) を使用して制御することができません。FIFO は、シーケンシャル アクセス パターンでのみ使用可能です。このコードでは任意/ランダム アクセスが必要なため、パフォーマンスを向上するにはピンポン ブロック RAM が必要です。ローカル配列のインプリメンテーションに必要なメモリが 2 倍の約 4 百万個のデータ サンプルになり、1 つの FPGA には大きすぎます。