3.2. OpenMP SIMD Constructs and Clauses#

OpenMP provides a set of SIMD constructs and clauses that enable developers to express data-level parallelism and take advantage of the SIMD capabilities of modern processors. These constructs and clauses allow for fine-grained control over the vectorization of loops and the optimization of SIMD code. In this section, we will introduce the key OpenMP SIMD constructs and clauses.

3.2.1. The simd Construct#

The simd construct is used to indicate that a loop should be vectorized, allowing multiple iterations of the loop to be executed concurrently using SIMD instructions. The purpose of the simd construct is to enable the compiler to generate efficient SIMD code for the loop.

The syntax for the simd construct in C/C++ is as follows:

#pragma omp simd [clause[[,] clause] ...]
for (/* loop iteration space */) {
    // Loop body
}

In Fortran, the syntax is:

!$omp simd [clause[[,] clause] ...]
do /* loop iteration space */
    ! Loop body
end do
!$omp end simd

By applying the simd construct to a loop, the developer hints to the compiler that the loop is a good candidate for vectorization. The compiler can then optimize the loop to utilize SIMD instructions, resulting in improved performance.

3.2.2. The declare simd Directive#

The declare simd directive is used to indicate that a function should be compiled for SIMD execution. It enables the creation of a SIMD version of the function that can be called from within a SIMD loop. The declare simd directive is particularly useful when a function contains operations that can be vectorized.

The syntax for the declare simd directive in C/C++ is:

#pragma omp declare simd [clause[[,] clause] ...]
return_type function_name(parameter_list)

In Fortran, the syntax is:

!$omp declare simd (function_name) [clause[[,] clause] ...]
function function_name(parameter_list)

By applying the declare simd directive to a function, the compiler generates a SIMD version of the function that can be invoked from within a SIMD loop. This allows for efficient vectorization of function calls, enabling better utilization of SIMD hardware.

3.2.3. Important SIMD Clauses#

OpenMP provides several clauses that can be used in conjunction with the simd construct and the declare simd directive to control the behavior of SIMD code. Some of the important SIMD clauses are:

  • aligned: The aligned clause is used to specify that certain data elements are aligned in memory. Aligned data access can improve the efficiency of SIMD operations.

  • linear: The linear clause is used to indicate that the value of a variable is incremented by a constant amount for each iteration of the SIMD loop.

  • private: The private clause specifies that each SIMD lane should have its own private copy of a variable.

  • lastprivate: The lastprivate clause is similar to the private clause but also ensures that the value of the variable from the last iteration is available after the SIMD loop.

  • reduction: The reduction clause is used to perform a reduction operation across SIMD lanes, such as summing up the values of a variable.

  • collapse: The collapse clause is used to collapse multiple nested loops into a single iteration space for SIMD execution.

  • safelen: The safelen clause specifies the maximum number of iterations that can be executed concurrently without violating dependencies.

  • simdlen: The simdlen clause is used to specify the preferred number of SIMD lanes to be used for the loop.

These clauses provide fine-grained control over the behavior of SIMD code and allow developers to optimize the performance of their SIMD loops.

In the next section, we will explore how to utilize SIMD directives for loop vectorization and provide examples of SIMD programming in OpenMP.