Turn on suggestions

Auto-suggest helps you quickly narrow down your search results by suggesting possible matches as you type.

Showing results for

- Intel Community
- Software
- Software Development Tools (Compilers, Debuggers, Profilers & Analyzers)
- Intel® C++ Compiler
- Not vectorized loop with if statement

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Mute
- Printer Friendly Page

luca_l_

Beginner

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

04-11-2017
11:24 AM

300 Views

Not vectorized loop with if statement

This is the first time that I try to vectorize a loop, I'm trying to optimize this code.

In particular, according to intel advisor, this is the best candidate for vectorization:

for (int j=-halfHeight; j<=halfHeight; ++j) { for(int i=-halfWidth; i<=halfWidth; ++i) { const float rx = ofsx + j * a12; const float ry = ofsy + j * a22; float wx = rx + i * a11; float wy = ry + i * a21; const int x = (int) floor(wx); const int y = (int) floor(wy); if (x >= 0 && y >= 0 && x < width && y < height) { // compute weights wx -= x; wy -= y; // bilinear interpolation *out++ = (1.0f - wy) * ((1.0f - wx) * im.at<float>(y,x) + wx * im.at<float>(y,x+1)) + ( wy) * ((1.0f - wx) * im.at<float>(y+1,x) + wx * im.at<float>(y+1,x+1)); } else { *out++ = 0; } } }

And this is the message in the optr file:

remark #15522: loop was not vectorized: loop control flow is too complex. Try using canonical loop form from OpenMP specification

How can I solve this?

Link Copied

6 Replies

SergeyKostrov

Valued Contributor II

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

04-12-2017
11:29 AM

300 Views

Anoop_M_Intel

Employee

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

04-12-2017
04:59 PM

300 Views

The generated the optimization report for helper.cpp using Intel C++ Compiler 17.0 Update 2 on Linux and saw the following for the loop:

Begin optimization report for: interpolate(const cv::Mat &, float, float, float, float, float, float, cv::Mat &)

Report from: Vector optimizations [vec]

LOOP BEGIN at helpers.cpp(219,4)

remark #15344: loop was not vectorized: vector dependence prevents vectorization

remark #15346: vector dependence: assumed OUTPUT dependence between *out (234:14) and *out (238:14)

remark #15346: vector dependence: assumed OUTPUT dependence between *out (238:14) and *out (234:14)

LOOP BEGIN at helpers.cpp(223,7)

remark #15344: loop was not vectorized: vector dependence prevents vectorization

remark #15346: vector dependence: assumed OUTPUT dependence between *out (234:14) and *out (238:14)

remark #15346: vector dependence: assumed OUTPUT dependence between *out (238:14) and *out (234:14)

LOOP END

LOOP END

By changing the code as shown below, you can successfully vectorize this loop:

for(int i=-halfWidth; i<=halfWidth; ++i, out++)

{

float wx = rx + i * a11;

float wy = ry + i * a21;

const int x = (int) floor(wx);

const int y = (int) floor(wy);

if (x >= 0 && y >= 0 && x < width && y < height)

{

// compute weights

wx -= x; wy -= y;

// bilinear interpolation

*out =

(1.0f - wy) * ((1.0f - wx) * im.at<float>(y,x) + wx * im.at<float>(y,x+1)) +

( wy) * ((1.0f - wx) * im.at<float>(y+1,x) + wx * im.at<float>(y+1,x+1));

} else {

*out = 0;

ret = true; // touching boundary of the input

}

}

The corresponding optimization report after the change is:

Begin optimization report for: interpolate(const cv::Mat &, float, float, float, float, float, float, cv::Mat &)

Report from: Vector optimizations [vec]

LOOP BEGIN at helpers.cpp(219,4)

remark #15542: loop was not vectorized: inner loop was already vectorized

LOOP BEGIN at helpers.cpp(223,7)

remark #15389: vectorization support: reference *out has unaligned access [ helpers.cpp(234,14) ]

remark #15389: vectorization support: reference *out has unaligned access [ helpers.cpp(238,14) ]

remark #15389: vectorization support: reference *out has unaligned access [ helpers.cpp(238,14) ]

remark #15381: vectorization support: unaligned access used inside loop body

remark #15328: vectorization support: indirect load was emulated for the variable <(im->data+*im->p*y)

remark #15328: vectorization support: indirect load was emulated for the variable <(im->data+*im->p*y)[x+1]>, masked, 64-bit indexed, part of address is result of call to function [ helpers.cpp(235,75) ]

remark #15328: vectorization support: indirect load was emulated for the variable <(im->data+*im->p*(y+1))

remark #15328: vectorization support: indirect load was emulated for the variable <(im->data+*im->p*(y+1))[x+1]>, masked, 64-bit indexed, part of address is result of call to function [ helpers.cpp(236,75) ]

remark #15305: vectorization support: vector length 4

remark #15309: vectorization support: normalized vectorization overhead 0.069

remark #15300: LOOP WAS VECTORIZED

remark #15450: unmasked unaligned unit stride loads: 1

remark #15451: unmasked unaligned unit stride stores: 1

remark #15457: masked unaligned unit stride stores: 1

remark #15458: masked indexed (or gather) loads: 4

remark #15475: --- begin vector cost summary ---

remark #15476: scalar cost: 262

remark #15477: vector cost: 236.250

remark #15478: estimated potential speedup: 1.100

remark #15482: vectorized math library calls: 2

remark #15487: type converts: 14

remark #15488: --- end vector cost summary ---

LOOP END

LOOP BEGIN at helpers.cpp(223,7)

<Remainder loop for vectorization>

LOOP END

LOOP END

SergeyKostrov

Valued Contributor II

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

04-13-2017
02:19 PM

300 Views

Serge_P_

Beginner

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

04-25-2017
06:16 PM

300 Views

The only problematic construct for vectorization in original code is *out++ = ... which is conditional induction. Its presence at both sides of loop makes loop vectorizable in theory, but in practice it requires sophisticated analysis from compiler to prove that dependency on 'out' value doesn't cross iteration boundary.

I don't have currently icc at my disposal, but something as simple as change below should enable vectorization. However, this code is quite poorly written from performance standpoint. It is highly advisable for such codes to implement one of 2 techniques to get rid of condition inside inner loop

`16` |
` ` `*out =` |

`17` |
` ` `(1.0f - wy) * ((1.0f - wx) * im.at<` `float` `>(y,x) + wx * im.at<` `float` `>(y,x+1)) +` |

`18` |
` ` `( wy) * ((1.0f - wx) * im.at<` `float` `>(y+1,x) + wx * im.at<` `float` `>(y+1,x+1));` |

`19` |
` ` `} ` `else` `{` |

`20` |
` ` `*out= 0;` |

21 | } |

22 | ++out; |

However, this code is quite poorly written from performance standpoint. It is highly advisable for such codes to implement one of 2 techniques to get rid of condition inside inner loop.

- Inner loop may be split into 2: one for interior points (x>0 && x < width) and one for the boundary points (x == 0 || x == width)
- Or input data may be padded at all sides to make logic for inner points work for entire data set.

The problem is that boundary condition is dynamic and so each vector iteration of inner loop will pay the price of mask construction and blending which is just waste of resources for interior iterations (most of all iterations).

luca_l_

Beginner

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

04-30-2017
01:51 AM

300 Views

Serge P. wrote:

The only problematic construct for vectorization in original code is *out++ = ... which is conditional induction. Its presence at both sides of loop makes loop vectorizable in theory, but in practice it requires sophisticated analysis from compiler to prove that dependency on 'out' value doesn't cross iteration boundary.

I don't have currently icc at my disposal, but something as simple as change below should enable vectorization. However, this code is quite poorly written from performance standpoint. It is highly advisable for such codes to implement one of 2 techniques to get rid of condition inside inner loop

16

*out =17

(1.0f - wy) * ((1.0f - wx) * im.at<float>(y,x) + wx * im.at<float>(y,x+1)) +18

( wy) * ((1.0f - wx) * im.at<float>(y+1,x) + wx * im.at<float>(y+1,x+1));19

} else {20

*out= 0;21

}22

++out;

However, this code is quite poorly written from performance standpoint. It is highly advisable for such codes to implement one of 2 techniques to get rid of condition inside inner loop.

- Inner loop may be split into 2: one for interior points (x>0 && x < width) and one for the boundary points (x == 0 || x == width)
- Or input data may be padded at all sides to make logic for inner points work for entire data set.
The problem is that boundary condition is dynamic and so each vector iteration of inner loop will pay the price of mask construction and blending which is just waste of resources for interior iterations (most of all iterations).

Could you please rewrite your answer with a better code formatting please?

Serge_P_

Beginner

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

05-09-2017
07:07 AM

300 Views

I will try but by some reason code looks fine in preview, but poorly when posted.

---

The only problematic construct for vectorization in original code is *out++ = ... which is conditional induction. Its presence at both sides of if statement makes loop vectorizable in theory, but in practice it requires sophisticated analysis from compiler to prove that dependency on 'out' value doesn't cross iteration boundary. I don't have currently icc at my disposal, but something as simple as change below should enable vectorization.

if (...)

{ *out = (1.0f - wy) * ((1.0f - wx) * im.at<float>(y,x) + wx * im.at<float>(y,x+1)) + ( wy) * ((1.0f - wx) * im.at<float>(y+1,x) + wx * im.at<float>(y+1,x+1)); } else { *out= 0; } ++out; /// <<< This is single inductive increment

However, this code overall is quite poorly written from performance standpoint. It is highly advisable for such codes to implement one of 2 techniques to get rid of condition inside inner loop.

- Inner loop may be split into 2: one for interior points (x>0 && x < width) and one for the boundary points (x == 0 || x == width).
- Or input data may be padded at all sides to make logic for inner points work for entire data set.

The problem is that boundary condition is dynamic and so each vector iteration of inner loop will pay the price of mask construction and blending which is just waste of resources for interior iterations (most of all iterations).

Topic Options

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page

For more complete information about compiler optimizations, see our Optimization Notice.