Developer Guide

Intel® oneAPI DPC++/C++ Compiler Handbook for FPGAs

ID 785441
Date 10/24/2024
Public
Document Table of Contents

initiation_interval Attribute

The initiation interval, or II, is the number of clock cycles between the launch of successive loop iterations.

Use the initiation_interval attribute to direct the Intel® oneAPI DPC++/C++ Compiler to attempt to set the II for the loop that follows the attribute declaration. If the Intel® oneAPI DPC++/C++ Compiler cannot achieve the specified II for the loop, then the compilation errors out.

Syntax

[[intel::initiation_interval(n)]]

The initiation_interval attribute applies to pipelined loops in single task kernels. Refer to Pipelining for information about loop pipelining.

The attribute parameter n is required and must be a positive constant expression of integer type. The parameter specifies a minimum number of clock cycles to wait between the beginnings of execution of successive loop iterations.

The higher the II value, the longer the wait before the subsequent loop iteration starts executing. Refer to Loop Analysis for information about II and compiler reports that provide you with details on the performance implications of II on a specific loop.

NOTE:

The initiation_interval attribute should only be applied to a pipelined loop in a single work-item (task) kernel.

If the throughput of a loop is important to the overall throughput of your kernel, you can use the initiation_interval attribute to force an II value of 1 even though this may result in lower fMAX.

For some loops in your kernel, specifying a higher II value with the initiation_interval attribute than the value the compiler chooses by default can increase the maximum operating frequency (fMAX) of your kernel without a decrease in throughput.

A loop is a good candidate to have a higher initiation_interval than the default if the loop meets the following conditions:

  • The loop is not critical to the throughput of your kernel.
  • The running time of the loop is small compared to other loops it might contain.

Example

Consider a case where your kernel has two distinct pipelineable loops:

  • A short-running initialization loop that has a loop-carried dependence
  • A long-running loop that does the bulk of your processing.

In this case, the compiler does not know that the initialization loop has a much smaller impact on the overall throughput of your design. If possible, the compiler attempts to pipeline both loops with an II of 1.

Because the initialization loop has a loop-carried dependence, it does have a feedback path in the generated hardware. To achieve an II with such a feedback path, some clock frequency might be forfeited. Depending on the feedback path in the main loop, the rest of your design could have run at a higher operating frequency.

If you specify [[intel::initiation_interval(2)]] on the initialization loop, then you are informing the compiler that it can be less aggressive in optimizing II for this loop. Less aggressive optimization allows the compiler to pipeline the path limiting the fMAX and allow your overall kernel design to achieve a higher fMAX.

The initialization loop takes longer to run with its new II. However, the decrease in the running time of the long-running loop due to higher fMAX compensates for the increased length in running time of the initialization loop.

TIP:

For additional information, refer to the FPGA tutorial sample "Loop Initiation Interval" on GitHub.