_for VS for

_for VS for

Hi,

I recently read the article 'When, and when not, to use the Intel ArBB _for loops'.

This article says to use _for loops 'to express serially dependent iterative computation. This is the case
where a computation must be done incrementally, with the current step
depending on the result of the previous step.'

Now I have a bunch of code which seems to just work fine as follows (using a regular for loop):

do_main() {
  dense v;

  for (int i=0; i < 12; i++) {
     call(function)(v);
  }
}

void function(dense& v) {
  //make modifications to v
  //by using map() to apply a stencil
}

This gives the same result (the same dense container v) as this code which uses the _for loop instead:

do_main() {
  dense v;

_for (i32 i=0, i < 12, i++) {
     call(function)(v);
  } _end_for
} 

void function(dense& v) {
  //make modifications to v
  //by using map() to apply a stencil
}

Why does this work with a regular for loop? Obviously the current step depends on the previous step.

Thanks.

5 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Hi,

This is a very interesting question! Thanks for bringing it up.

Function "do_main" in your code is a regular C/C++ function. From ArBB's perspective, it is uncaptured code. For an explanation about capture, please refer to these KB articles (link, link). Code inside this function is executed at JIT time. Winthin this context, although the _for loop is an ArBB construct, it is executed at JIT time, as if it was a regular C/C++ for loop. So in this situation, there isn't a difference between _for and for.

The difference between _for and for is important when you use them inside captured code. That is, the code to be captured into a closure. The last section of the article 'When, and when not, to use the Intel ArBB _for loops' explains the difference in detail.

Hi,

Thank you for your response. Still, this closure/capture and arbb controlflow vs regular control flow is confusing to me.
Imagine a recursive construct as follows:

void do_main() {
 dense v;
 do_something(v, 5);
 }

do_something(dense &v, int count) {
  for (int i=0; i < 12; i++) { 
     call(function)(v); 
  } 

  if (count > 1) {
     do_something(v, count-1);
  }
}

Is there a difference with:

void do_main() {
  dense v;
  call(do_something)(v, 5);
}

do_something(dense &v, i32 count) {
  _for (i32 i=0, i < 12, i++) { 
     call(function)(v); 
  } _end_for

 _if (count > 1) {
     call(do_something)(v, count-1);
  } _end_if 
}

? Actually, my code hangs in the latter case, while in the former case it seems to work. Is it also supposed to be equivalent? And if they are not equivalent, which one does the intuitive thing?

Thanks.

Hi,

The problem you saw is because recursion of an ArBB function is not currently supported. If you remove the recursion from your second example then it works fine.

Your first example works because function 'do_something' was not an ArBB function. It is a regular C++ function and its recursion works fine just like any other recursions in C++.

In your second example, because the loop count is a constant (12), you can use either for or _for. However, if you use 'for' then the loop is fully unrolled at JIT time. If the loop count is not a constant then you can only use _for. For example:

void do_something(dense &v, i32 count)
{
    // Cannot use 'for' loop here because loop count is NOT a constant
    _for (i32 i = 0, i < count, i++) {
        function(v);  
   } _end_for
}

Hope this helps.

Great. Thanks for your answer!

Leave a Comment

Please sign in to add a comment. Not a member? Join today