たたみ込みフィルターには、3 つの独立した CU が含まれ、それぞれがビデオ画像ストリームから 1 つのカラー チャネルを処理します。この例では、プロジェクトをシンプルに保って VSC に集中するため、実際のビデオ ストリームは使用しません。この例のホスト コードは、VSC 固有のコードを使用するソフトウェア関数に渡されるカラー チャネル 3 つを持つランダム イメージを生成するだけです。これにより、C スレッドがホストからデバイス、および compute()
呼び出しへのデータの送受信をするようになります。
この関数は、すべてのフィルター パラメーターとデータ ポインターをソースおよびデスティネーション イメージに渡します。次のコード部分は、この関数の定義を示しています。基本的なステップは、次のとおりです。
- バッファー プール ハンドル (
srcBufPool
...) を作成して、ホストとデバイス間のデータの送受信をイネーブルにします。属性でバッファーが入力か出力かを示します。 - ラムダ関数を使用して
conv_acc::send_while()
を呼び出します。ラムダ関数は、デバイス上でバッファーを割り当て、ホスト データをデバイス バッファーにコピーしてから、compute()
関数を呼び出します (これにより、ハードウェア アクセラレーションされた関数が実行されます)。send_while()
は、true
を戻し続ける限り、ラムダ関数を呼び出し続けます。 - ラムダ関数を使用する
conv_acc::receive_all_in_order()
を呼び出し、処理されたバッファーを受信します。 -
join()
呼び出しを使用して、待機し、すべてを同期します。
ヒント: さまざまな関数の説明は、VPP_ACC クラスの API を参照してください。
#include "conv_filter_acc_wrapper.hpp"
int conv_filter_execute_fpga(
const char coeffs[FILTER_V_SIZE][FILTER_H_SIZE],
float factor,
short bias,
unsigned short width,
unsigned short height,
unsigned int numImages,
YUVImage srcImage,
YUVImage dstImage
)
{
auto srcBufPool = conv_acc::create_bufpool(vpp::input);
auto dstBufPool = conv_acc::create_bufpool(vpp::output);
auto coeffsBufPool = conv_acc::create_bufpool(vpp::input);
int run = 0;
int dataSizePerChannel = width * height ;
// sending input
conv_acc::send_while([=]()->bool {
conv_acc::set_handle(run);
unsigned char * srcBuf = (unsigned char *)conv_acc::alloc_buf(srcBufPool, 3*dataSizePerChannel);
unsigned char * dstBuf = (unsigned char *)conv_acc::alloc_buf(dstBufPool, 3*dataSizePerChannel);
char * coeffsBuf = ( char *)conv_acc::alloc_buf(coeffsBufPool, FILTER_V_SIZE*FILTER_H_SIZE);
// initialize all input data before parallel computes
unsigned char * srcChannel[3] = {srcImage.yChannel, srcImage.uChannel, srcImage.vChannel};
for (int ch = 0; ch < 3; ch++){
std::memcpy(srcBuf+ch*dataSizePerChannel, srcChannel[ch], dataSizePerChannel);
}
std::memcpy(coeffsBuf,coeffs,256);
// execute conv_acc<NCU> parallel computes
for (int ch = 0; ch < 3; ch++){
conv_acc::compute(coeffsBuf,
factor,
bias,
width,
height,
srcBuf + ch*dataSizePerChannel,
dstBuf + ch*dataSizePerChannel);
}
return (++run < numImages);
});
// receive lambda function for receive thread
conv_acc::receive_all_in_order([=]() {
int run = conv_acc::get_handle();
unsigned char * dstBuf = (unsigned char *)conv_acc::get_buf(dstBufPool);
unsigned char * dstChannel[3] = {dstImage.yChannel, dstImage.uChannel, dstImage.vChannel};
for (int ch = 0; ch < 3; ch++){
std::memcpy(dstChannel[ch], dstBuf+ch*dataSizePerChannel, dataSizePerChannel);
}
});
// wait for both loops to finish
conv_acc::join();
return 0;
}