Calls to virtual methods are always indirect because the function address is calculated during runtime. Do the following to fix:
- Force vectorization of the source loop using SIMD instructions and/or create a SIMD version of the function(s) using a directive:
Target Directive Source loop #pragma omp simd Inner function definition or declaration #pragma omp declare simd - Update to Intel Compiler 17.x or higher. Or replace the virtual method with a direct function call.
...
virtual double foo(double x) { return x+1; }
...
// virtual indirect call
sum += obj->foo(a[k]);
...struct A {
virtual double foo(double x) { return x+1; }
};
struct B : public A {
double foo(double x) override { return x-1; }
};
...
A* obj = new B();
double sum = 0.0;
#pragma omp simd reduction(+:sum)
for (int k = 0; k < N; ++k) {
// virtual indirect call
sum += obj->foo(a[k]);
}
......
#pragma omp declare simd
virtual double foo(double x) { return x+1; }
...
sum += ((B*)obj)->B::foo(a[k]);
...struct A {
// Intel Compiler 17.x or higher could vectorize call to virtual method
#pragma omp declare simd
virtual double foo(double x) { return x+1; }
};
...
sum = 0.0;
#pragma omp simd reduction(+:sum)
for (int k = 0; k < N; ++k) {
// step for Intel Compiler 16.x or lower:
// if you know the method to be called,
// replace virtual call with direct one
sum += ((B*)obj)->B::foo(a[k]);
}
...- omp simd, omp declare simd in OpenMP* Pragmas Summary
- Getting Started with Intel Compiler Pragmas and Directives and Vectorization Resources for Intel® Advisor Users