分层计算图 - 2023.2 简体中文

AI 引擎内核与计算图编程指南 (UG1079)

Document ID
UG1079
Release Date
2023-12-04
Version
2023.2 简体中文
每个计算图均可由内核与子计算图混合而成。如果要例化多个内核,则可将其声明为阵列或以特定名称来声明。在以下示例中,通过模板参数来指定将声明为阵列的内核的数量:
template <int NK>
class MultiKernelGraph: public adf::graph {
private:
  adf::kernel k[NK];

public:
  adf::port<input> din;
  adf::port<output> dout;

  MultiKernelGraph() {
    for(int i=0;i<NK;i++)
    {
      k[i] = adf::kernel::create(passthrough);
      adf::source(k[i]) = "kernels.cpp";

      adf::runtime<ratio>(k[i]) = 0.9;
    }
    adf::connect(din, k[0].in[0]);
    for(int i=0;i<NK-1;i++)
      adf::connect(k[i].out[0], k[i+1].in[0]);
    adf::connect(k[NK-1].out[0], dout);
  };
};
class TestGraphMulti: public adf::graph {
public:
  adf::input_plio plin;
  adf::output_plio plout;

  MultiKernelGraph<3> Multi;

  TestGraphMulti()
  {
    plin = adf::input_plio::create("input2",adf::plio_64_bits,"data/Input_64.txt",500);
    adf::connect(plin.out[0],Multi.din);

    plout = adf::output_plio::create("output2",adf::plio_64_bits,"data/Output2.txt",500);
    adf::connect(Multi.dout,plout.in[0]);
  };
};
图 1. 计算图视图

如前文所示,每个计算图均可包含内核与子计算图。测试激励文件 .cpp 代码可以例化多个计算图,并独立运行每个计算图。

TestGraphSimple Simple_UnitTest;
TestGraphMulti Multi_UnitTest;

int main(int argc, char ** argv) {

  Simple_UnitTest.init();
  Multi_UnitTest.init();

  Simple_UnitTest.run(NFRAMES*NITERATIONS);
  Multi_UnitTest.run(NFRAMES*NITERATIONS);

  Simple_UnitTest.end();
  Multi_UnitTest.end();
  return 0;
}

Vitis IDE 会在计算图视图中显示 2 个独立计算图。

图 2. 多个计算图

这 2 个计算图还可在第三个计算图内例化,这第三个计算图在测试激励文件内进行例化:

class TestGraph: public adf::graph {
public:
  adf::input_plio plin1,plin2;
  adf::output_plio plout1,plout2;

  SimplestGraph Simple;
  MultiKernelGraph Multi;

  TestGraph()
  {
    plin1 = adf::input_plio::create("input1",adf::plio_64_bits,"data/Input_64.txt",500);
    adf::connect(plin1.out[0],Simple.din);

    plout1 = adf::output_plio::create("output1",adf::plio_64_bits,"data/Output1.txt",500);
    adf::connect(Simple.dout,plout1.in[0]);

    plin2 = adf::input_plio::create("input2",adf::plio_64_bits,"data/Input_64.txt",500);
    adf::connect(plin2.out[0],Multi.din);

    plout2 = adf::output_plio::create("output2",adf::plio_64_bits,"data/Output2.txt",500);
    adf::connect(Multi.dout,plout2.in[0]);

  };
};
TestGraph UnitTest;

int main(int argc, char ** argv) {

  UnitTest.init();
  UnitTest.run(NFRAMES*NITERATIONS);
  UnitTest.end();
  return 0;
}
图 3. 组合计算图视图

您也可以创建更为复杂的计算图,包括串行和并行内核,以及可在整个计算图内多次拆分合并数据流的计算图,并使用缓冲器和串流通过 AI 引擎阵列来传输数据。

VeryComplexGraph() {
  // Declare Kernels
  for(int i=0;i<2;i++)
  {
    simple[i] = adf::kernel::create(passthrough);
    adf::source(simple[i]) = "kernels.cpp";
    adf::runtime<ratio>(simple[i]) = 0.9;
  }

  // Connections
  // Inputs
  connect(din[0],split[0].din);
  connect(din[1],split[1].din);

  // Outputs
  connect(merge[2].dout,dout[0]);
  connect(split[3].dout[0],dout[1]);
  connect(split[3].dout[1],dout[2]);

  // Internal connections
  connect(split[0].dout[0],multi3.din);
  connect(multi3.dout,merge[2].din[0]);
  connect(split[0].dout[1],merge[0].din[0]);
  connect(split[1].dout[0],merge[0].din[1]);
  connect(merge[0].dout,simple[0].in[0]);
  connect(simple[0].out[0],split[2].din);
  connect(split[2].dout[0],multi2[1].din);
  connect(multi2[1].dout,merge[2].din[1]);
  connect(split[2].dout[1],simple[1].in[0]);
  connect(simple[1].out[0],merge[1].din[0]);
  connect(split[1].dout[1],multi2[0].din);
  connect(multi2[0].dout,merge[1].din[1]);
  connect(merge[1].dout,split[3].din);
};
图 4. 复杂计算图视图

在此计算图视图中,显示了一条复杂的数据流,此数据流在多个点处分离与汇合。如果数据流中某一部分需要进出 PL,您将看到在链接阶段连接到 PL 内核的对应输出端口和输入端口。