# Load VTA parameters from the 3rdparty/vta-hw/config/vta_config.json file env = vta.get_env()
配置内容和 FPGA 平台上的配置内容一致即可
Line 50:配置 RPC 远程的 IP 和端口,注意到这里用的环境变量字段和我们之前添加的并不完全一样,所以要进行修改
# We read the Pynq RPC host IP address and port number from the OS environment host = os.environ.get("VTA_RPC_HOST", "192.168.2.99") port = int(os.environ.get("VTA_RPC_PORT", "9091"))
if env.TARGET == "pynq"or env.TARGET == "de10nano":
# Make sure that TVM was compiled with RPC=1 assert tvm.runtime.enabled("rpc") remote = rpc.connect(host, port) vta.reconfig_runtime(remote) vta.program_fpga(remote, bitstream=None)
Line 165:创建矩阵的占位符 A、B 和中间张量 A_buf、B_buf。
两个 buf 变量会在运算过程中存储在 VTA 的片上缓存中,计算乘法结果后产生 C_buf,复制回结果张量 C 中,完成运算。过程如图所示:
Line 202:定义了输入数据内部和外部两个规约轴 ko 和 ki,并执行了 VTA 的矩阵乘法操作。
s = te.create_schedule(C.op) # Set the intermediate tensor's scope to VTA's on-chip buffers s[A_buf].set_scope(env.inp_scope) s[B_buf].set_scope(env.wgt_scope) s[C_buf].set_scope(env.acc_scope)
Line 339:DMA 传输。使用 compute at 将缓冲区的复制操作结合在矩阵乘法的循环中;再使用 pragma 原语控制计算 A_buf、B_buf 和 C 时应该直接通过 env.dma_copy 操作从内存中直接传输
# Move buffer copy into matrix multiply loop s[A_buf].compute_at(s[C_buf], ko) s[B_buf].compute_at(s[C_buf], ko) # Tag the buffer copies with the DMA pragma to insert a DMA transfer s[A_buf].pragma(s[A_buf].op.axis[0], env.dma_copy) s[B_buf].pragma(s[B_buf].op.axis[0], env.dma_copy) s[C].pragma(s[C].op.axis[0], env.dma_copy)
Line 371:张量化(Tensorization),这部分没有看明白,这一小块好像是用 reorder 重排了循环的顺序再进行了张量化(?)这也是算法中关于调度部分的结束
Line 389:TVM 编译,在创建一个 GEMM 内核后,我们可以将调度内容封装为一个 TVM 函数,保存在内核里,并将其上传、加载在 RPC 服务器中