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

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

2.5.1. 查看循环信息

Loops Analysis报告包含有关设计中所有循环(coalesced、unrolled和fused loops)的信息以及其展开(unroll)状态。还报告有助于您检查是否 Intel® FPGA SDK for OpenCL™ Offline Compiler可以最限度地提高您的kernel的吞吐量。

注: fMAX II报告现已启用,其信息并入Loop Analysis报告中。

要查看有关吞吐量瓶颈的详细信息,请使用Bottlenecks查看器。

要访问该报告,请点击Throughput Analysis > Loop Analysis。左手边的Loops List窗格显示循环的类型,如下:

  • Fused loops
  • Fused subloops
  • Coalesced loops
  • Fully unrolled loops
  • Partial unrolled loops
  • Regular loops

Loops Analysis报告采集所有块上的如下关键性能指标:

  • Source Location:显示源代码中的循环位置。
  • Pipelined:指示循环的主体是否流水线化。流水线允许并发处理许多数据项(在同一时钟周期),并同时通过保持数据路径中硬件的占用状态来对其加以有效利用。
  • II:显示循环的可持续启动间隔(II)。循环处理数据是流水线并行性的另一个来源。当您流水线化循环时,循环的下一次迭代在前一次迭代完成之前就开始。

    您可以通过由于解决迭代间任何依赖项而需要的时钟周期来确认迭代间的时钟周期数。您可以将该数称为循环的启动间隔(II)。

    Intel® FPGA SDK for OpenCL™ Offline Compiler自动认证这些依赖项并构建硬件来解决这些依赖项,同时最小化II。请参阅指定一个循环启动间隔(II)了解其他信息。

  • Scheduled f MAX 显示循环运行时调度的最大时钟频率。fMAX是已更新的寄存器输出的最大速率。

    两个连续的寄存器之间信号的物理传播延迟会限制时钟速度。该传播延迟是数据路径中Boolean(布尔)逻辑复杂性的函数。具有最多该逻辑(以及最高延迟)的数据路径会限制整个电路的速度,您可将该数据路径称为关键路径(critical path)。

    fMAX计算的是关键路径延迟的倒数。高fMAX是可取的,因为在没有其他瓶颈的情况下,它与高性能直接相关联。offline编译器尝试根据是否设置了fMAX目标以及是否为每个循环设置了#pragma II来优化所调度fMAX的不同目标的内核。fMAX目标是一个强硬建议,即使无法达到该fMAX,编译器也不会出错,然而如果编译器无法达到需要的II,那么#pragma II会触发错误。Loops report中显示针对代码的每个块实现的fMAX

    以下表格概括了 Intel® FPGA SDK for OpenCL™ Offline Compiler中调度程序(scheduler)的行为:

    明确指定fMAX? 明确指定II? 编译器行为
    No No 使用试探法实现最佳fMAX/II权衡。
    No Yes 实现响应循环的II(可能未达到最佳可能的fMAX)最佳尝试。
    Yes No 实现指定的fMAX(可能未达到最佳可能的II)的最佳尝试。
    Yes Yes 在给定II的情况下实现指定fMAX 的最佳尝试。如果无法实现要求的II,则编译器会出错。
    注: 如果您将目标fMAX用于命令行或者某个kernel,则请将#pragma II = <N>用作设计中的关键性能循环。
  • Latency:显示一次循环完成一个或多个指令所索要的时钟周期数。通常,您希望低延迟。然而,降低的延迟往往导致减低的fMAX
  • Speculated Iterations:显示循环推测。循环推测是一种优化技术,通过在确定循环是否已经退出之前就允许启动未来的迭代来实现更有效率的循环流水线。请参阅循环推测了解更多信息。
  • Max Interleaving Iterations:指示可以同时执行的内部循环交叉存取调用次数。请参阅循环交叉存取控制了解更多信息。

您可使用Loops Analysis报告来确定在循环中部署一个或者多个pragma的位置。请参阅Intel FPGA SDK for OpenCL编程指南中的以下pragma文档:

OpenCL内核实例

以下是一个包含4个循环的OpenCL内核实例:

 1  // ND-Range kernel with unrolled loops
 2  __attribute((reqd_work_group_size(1024,1,1)))
 3  kernel void t (global int * out, int N) {
 4    int i = get_global_id(0);
 5    int j = 1;
 6    for (int k = 0; k < 4; k++) {
 7      #pragma unroll
 8      for (int n = 0; n < 4; n++) {
 9        j += out[k+n];
10      }
11    }
12    out[i] = j;
13
14    int m = 0;
15    #pragma unroll 1
16    for (int k = 0; k < N; k++) {
17      m += out[k/3];
18    }
19    #pragma unroll
20    for (int k = 0; k < 6; k++) {
21      m += out[k];
22    }
23    #pragma unroll 2
24    for (int k = 0; k < 6; k++) {
25      m += out[k];
26    }
27    out[2] = m;
28  }

本设计实例的循环分析报告突出显示代码中定义的不同类型循环的展开策略(unrolling strategy)。

Intel® FPGA SDK for OpenCL™ Offline Compiler基于源代码执行如下循环展开策略:

  • 完全展开第一个循环内的内部循环(第8行)因为#pragma unroll规范
  • 不展开第二个外循环,Block4(第16行),因为#pragma unroll 1规范
  • 完全展开第三个外循环(第20行)因为#pragma unroll规范
  • 将第四个外循环,Block5(第24行)展开两次因为#pragma unroll 2规范