The standard template for vectorization seems to be thus:
#define N 100
double arr[N];
double func(int i);
for(int i = 0; i <N; i++)
arr[i] = func(i);
where all of the indices are consecutively accessed.
However, I have a situation where not all Nelements of arr need updation. The template I have is as follows:
#define N 100
double arr[N];
double func(int i);
int indexset[N];//this indexset has the indices of arr[] that get updated
int number_in_index_set;
//E.g., if I only need to update arr[4] and arr[10], number_in_index_set = 2
//indexset[0] = 4 and indexset[1] = 10
for(int i = 0; i <number_in_index_set; i++)
arr[indexset[i]] = func(indexset[i]);
In this case, Intel Advisor reports that this loop was not vectorized because loop iteration count cannot be computed before executing the loop. In my application, this loop is executed for different subsets of indices, and for each such subset, number_in_index_set and indexset[] would change correspondingly.
I have two questions:
(1)What does it mean for the problematic loop to even be vectorized? The array indices are not consecutive, so how would the compiler even go about vectorizing the loop?
(2)Assuming vectorization is possible, as Intel Advisor seems to suggest, how can the loop in question be safely vectorized? The recommendation from Intel Advisor are thus:
For Example 1, where the loop iteration count is not available before the loop executes: If the loop iteration count and iterations lower bound can be calculated for the whole loop: Move the calculation outside the loop using an additional variable. Rewrite the loop to avoid goto statements or other early exits from the loop. Identify the loop iterations lower bound using a constant. For example, introduce the new limit variable: void foo(float *A) { int i; int OuterCount = 90; int limit = bar(int(A[0])); while (OuterCount > 0) { for (i = 1; i < limit; i++) { A[i] = i + 4; } OuterCount--; } } For Example 2, where the compiler cannot determine if there is aliasing between all the pointers used inside the loop and loop boundaries: Assign the loop boundary value to a local variable. In most cases, this is enough for the compiler to determine aliasing may not occur. You can use a directive to accomplish the same thing automatically. Target ICL/ICC/ICPC Directive Source loop #pragma simd or #pragma omp simd Do not use global variables or indirect accesses as loop boundaries unless you also use one of the following: Directive to ignore vector dependencies Target ICL/ICC/ICPC Directive Source loop #pragma ivdep restrict keyword.
Specifically, which of the above recommendations are guaranteed to ensure safe vectorization?