Intel® FPGA SDK for OpenCL™ Pro Edition: 最佳实践实践指南

ID 683521
日期 9/26/2022
Public
文档目录

3.5. 通道

Intel® FPGA SDK for OpenCL™的通道实现提供了一种灵活的方式来将数据从一个内核传递到另一个内核。

在您的内核代码中声明通道时,请在声明之前加上关键字channel

例如:

channel long16 myCh __attribute__((depth(16)));

在HTML报告中,区域报告将通道区域映射到源代码中的声明行。报告通道和通道阵列的宽度和深度。

注: 已实现的通道深度可能与您在通道声明中指定的深度不同。英特尔FPGA SDK for OpenCL Offline Compiler可以实现在移位寄存器或者RAM block中实现通道。离线编译器基于通道深度决定通道实现的类型。

depth属性被视为最小深度规范。离线编译器可能会因为以下原因增加深度:

  • 指令调度要求。可能因为以下原因出现该要求:
    • 通过多个内核平衡重新收敛的路径。

      当多个路径从一个内核通过通道退到另一个内核和其他内核时,这些通道上的深度可能增加,以平衡全部这些路径之间的延迟。这样是一次吞吐量优化,因为不平和的路径可能导致流水线停顿。

    • 对包含non-blocking(非阻塞)写入通道的循环实现较低的II。

      离线编译器可能增加该通道的深度以实现较低的循环II。

      考虑以下循环,仅当在前一个迭代中对my_channel成功非阻塞写时,该循环从全局存储器读取next_val

      bool write_valid = true;
      int next_val = 0;
      while (not_done) {
         if (write_valid) {
            next_val = *global_mem_ptr;
            global_mem_ptr++;
         }
         write_valid = write_channel_nb_intel(my_channel, next_val);
         not_done = some_fn(next_val);
      }

      通过最简单的实现,该循环有一个非常高的II,因为高延迟全局存储器读必须要在写入通道之前完成,并计算write_valid的下一个值。要从II关键路径中删除全局读取,可以改为编译器检查my_channel是否由足够空间接受从全局存储器中读取的任何值,然后再进行实际的全局读取。通道满度(fullness)检查需要一个时钟周期,因此,一旦通道满度检查完成,下一个循环迭代就可以开始,为此该循环的给定II=1。为使生成的硬件正确工作,必须通过全局读取的延迟来加深通道,或者准确来说,调度通道满度检查和实际写入之间的距离,可能略大于全局读取。如果您不想在这种情况下加深您的通道,就请识别并删除循环携带的依赖项,该依赖项涉及来自有效write_channel_nb_intel()调用的有效返回。

  • 底层FIFO实现的本性(nature)。如果选选择的实现不能支持需要的确切深度,并且必须增加到下一个支持的大小,就会发生这种情况。