C++ テンプレート サポート - 2023.2 日本語

AI エンジン カーネルおよびグラフ プログラミング ガイド (UG1079)

Document ID
UG1079
Release Date
2023-12-04
Version
2023.2 日本語

テンプレートは、C++ の強力なツールです。データ型をパラメーターとして渡すことにより、異なるデータ型をサポートするためにコードを記述し直す必要がなくなります。テンプレートは、マクロと同様にコンパイル時に展開されます。違いは、コンパイラがテンプレートを展開する前に型チェックを実行することです。ソース コードにはテンプレート関数とクラス定義が含まれていますが、コンパイルされたコードには同じ関数またはクラスの複数のコピーを含めることができます。型パラメーター、型パラメーター以外のパラメーター、デフォルト引数、スカラー パラメーター、およびテンプレート パラメーターをテンプレートに渡すことができます。それに応じて、コンパイラによりテンプレートに関数またはクラスがインスタンシエートされます。

  • 汎用 C++ テンプレート機能をサポート。
  • サポートされているデータ型 (T) とカーネル間の接続の種類:
    • データ型 (T): int8uint8int16uint16cint16int32uint32cint32int64uint64floatint4uint4bfloat16
      重要: acc48 および cacc48 データ型は、テンプレート ストリーム接続ではサポートされません。
  • コンパイラでは、テンプレート カーネルのコンパイル済みヘッダーはサポートされません。

関数テンプレート

関数テンプレートのソース コードは、異なるデータ型に使用可能な汎用関数を定義します。次に、関数テンプレートの例を示します。

// add.h

using namespace adf;
template<typename ELEMENT_TYPE, int FACTOR, size_t NUM_SAMPLES> void add(input_buffer<ELEMENT_TYPE> &in, output_buffer<ELEMENT_TYPE> &out);
// add.cpp

#include <aie_api/aie.hpp>
#include <aie_api/aie_adf.hpp>
using namespace adf;
template<typename ELEMENT_TYPE, int FACTOR, size_t NUM_SAMPLES> void add(input_buffer<ELEMENT_TYPE> &in, output_buffer<ELEMENT_TYPE> &out){
  auto inIter=aie::begin(in);
  auto outIter=aie::begin(out);
  for (int i=0; i<NUM_SAMPLES; i++){
    ELEMENT_TYPE value = *inIter++;
    value += FACTOR;
    *outIter++=value;
  }
}
// graph.h
mygraph()
{
    k[0] = kernel::create(add<int32, 6, 8>);
    k[1] = kernel::create(add<int16, 3, 8>);
    for (int i=0; i<NUM_KERNELS; i++)
    {
        runtime<ratio>(k[i]) = 0.3;
        source(k[i]) = "src/add.cpp";
    }

    connect(in[0], k[0].in[0]);
    connect(k[0].out[0], out[0]);

    connect(in[1], k[1].in[0]);
    connect(k[1].out[0], out[1]);
    
    dimensions(k[0].in[0])={8};
    dimensions(k[0].out[0])={8};
    dimensions(k[1].in[0])={8};
    dimensions(k[1].out[0])={8};
}

説明:

  • add.h: テンプレート add() 関数を定義します。
  • add.cpp: テンプレート add() 関数のコードを定義します。
  • graph.h: mygraph クラス内のテンプレート add() 関数を使用します。

クラス テンプレート

クラス テンプレートは、関数テンプレートと同様、特定のデータ型とは独立したオブジェクトをクラスで定義する場合に便利です。次に、クラス テンプレートの例を示します。

// fir.h
...
template<size_t NUM_COEFFS, typename ELEMENT_TYPE> class FIR
{
private:
    ELEMENT_TYPE (&coeffs)[NUM_COEFFS];
    ELEMENT_TYPE tapDelayLine[NUM_COEFFS];
    uint32 numSamples;

public:
    FIR(ELEMENT_TYPE(&coefficients)[NUM_COEFFS], uint32 samples);

    void filter(input_buffer<ELEMENT_TYPE> &in, output_buffer<ELEMENT_TYPE> &out);

    //user needs to write this function to register necessary info
    static void registerKernelClass()
    {
        REGISTER_FUNCTION(FIR::filter);
        REGISTER_PARAMETER(coeffs);
    }
}
// fir.cpp
...
template<size_t NUM_COEFFS, typename ELEMENT_TYPE> FIR<NUM_COEFFS, ELEMENT_TYPE>::FIR(ELEMENT_TYPE(&coefficients)[NUM_COEFFS], uint32 samples):coeffs(coefficients)
{
    ...
}

template<size_t NUM_COEFFS, typename ELEMENT_TYPE> void FIR<NUM_COEFFS,ELEMENT_TYPE>::filter(input_buffer<ELEMENT_TYPE> &in, output_buffer<ELEMENT_TYPE> &out)
{
    ...
}
// graph.h
...
mygraph()
{
    k1 = kernel::create_object<FIR<12, int32>>(std::vector<int>({ 180, 89, -80, -391, -720, -834, -478, 505, 2063, 3896, 5535, 6504 }), 8);
    runtime<ratio>(k1) = 0.1;
    source(k1) = "src/fir.cpp";
    headers(k1) = { "src/fir.h" };

    k2 = kernel::create_object<FIR<15, int32>>(std::vector<int>({ -21, -249, 319, -78, -511, 977, -610, -844, 2574, -2754, -1066, 18539, 0, 0, 0 }), 8);
    runtime<ratio>(k2) = 0.1;
    source(k2) = "src/fir.cpp";
    headers(k2) = { "src/fir.h" };
    ...
}

説明:

  • fir.h: クラス FIR が宣言されているクラス テンプレートを定義します。
  • fir.cpp: クラス FIR のインプリメンテーションとクラス FIR メンバー関数の filter インプリメンテーションを含みます。
  • graph.h: mygraph クラス内のテンプレート クラス FIR インスタンシエーションを示します。