每个计算图均可由内核与子计算图混合而成。如果要例化多个内核,则可将其声明为阵列或以特定名称来声明。在以下示例中,通过模板参数来指定将声明为阵列的内核的数量:
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 内核的对应输出端口和输入端口。