Thread overview
skipping a statemnet from inside a repeating block
Feb 14, 2013
Gopan
Feb 14, 2013
John Colvin
Feb 16, 2013
Gopan
Feb 16, 2013
Gopan
Feb 14, 2013
Andrea Fontana
Feb 16, 2013
Gopan
Feb 16, 2013
John Colvin
Feb 15, 2013
Diego
Feb 16, 2013
Gopan
February 14, 2013
Dear Friends,

I have a callback function which will be called back so many times, say at every second for a week.

void TimerCallback(int number)
{
    Statement_1;

    if(number == MY_MAGIC_NUMBER)
    {
        /*
        I have been waiting for this so far.  Now, I have got want I want.		
        So, I don't want to execute the the above if condition for further callbacks.

        IS THERE ANY TECHNIQUE by which I can say HERE that,
        from Statement_1, the control can directly go to Statement_3,
        skipping the evaluation of the above if condition?
        If it is not possible, is it a limitation at the
        micro-processor architecture level?
        */
    }

    Statement_3;
}

Thank you.


February 14, 2013
On Thursday, 14 February 2013 at 13:14:47 UTC, Gopan wrote:
> Dear Friends,
>
> I have a callback function which will be called back so many times, say at every second for a week.
>
> void TimerCallback(int number)
> {
>     Statement_1;
>
>     if(number == MY_MAGIC_NUMBER)
>     {
>         /*
>         I have been waiting for this so far.  Now, I have got want I want.		
>         So, I don't want to execute the the above if condition for further callbacks.
>
>         IS THERE ANY TECHNIQUE by which I can say HERE that,
>         from Statement_1, the control can directly go to Statement_3,
>         skipping the evaluation of the above if condition?
>         If it is not possible, is it a limitation at the
>         micro-processor architecture level?
>         */
>     }
>
>     Statement_3;
> }
>
> Thank you.

Not internally to the function, no.

In truth, there's no need to do this. Branch prediction (http://en.wikipedia.org/wiki/Branch_predictor) should reduce the cost hugely.
Also, a comparison is only going to be 1 cycle, saving a single cycle per second is irrelevant.
February 14, 2013
On Thursday, 14 February 2013 at 13:14:47 UTC, Gopan wrote:
> Dear Friends,
>
> I have a callback function which will be called back so many times, say at every second for a week.
>
> void TimerCallback(int number)
> {
>     Statement_1;
>
>     if(number == MY_MAGIC_NUMBER)
>     {
>         /*
>         I have been waiting for this so far.  Now, I have got want I want.		
>         So, I don't want to execute the the above if condition for further callbacks.
>
>         IS THERE ANY TECHNIQUE by which I can say HERE that,
>         from Statement_1, the control can directly go to Statement_3,
>         skipping the evaluation of the above if condition?
>         If it is not possible, is it a limitation at the
>         micro-processor architecture level?
>         */
>     }
>
>     Statement_3;
> }
>
> Thank you.

Maybe you can write 2 different callbacks, one with if, one without and switch between them. Maybe with a compile-time code generation to avoid code repetitions... Just for a int comparison or is it a different long operation?

February 15, 2013
On Thursday, 14 February 2013 at 13:14:47 UTC, Gopan wrote:
> Dear Friends,
>
> I have a callback function which will be called back so many times, say at every second for a week.
>
> void TimerCallback(int number)
> {
>     Statement_1;
>
>     if(number == MY_MAGIC_NUMBER)
>     {
>         /*
>         I have been waiting for this so far.  Now, I have got want I want.		
>         So, I don't want to execute the the above if condition for further callbacks.
>
>         IS THERE ANY TECHNIQUE by which I can say HERE that,
>         from Statement_1, the control can directly go to Statement_3,
>         skipping the evaluation of the above if condition?
>         If it is not possible, is it a limitation at the
>         micro-processor architecture level?
>         */
>     }
>
>     Statement_3;
> }
>
> Thank you.

You can use static variables inside that function:

void
TimerCallback(int number) {
    statement_1;

    static bool i_found_my_magic_number = false;

    if(!i_found_my_magic_number && number == MY_MAGIC_NUMBER) {
        i_found_my_magic_number = true;
        // Do what you need.
    }

    statement_3;
}

Static variables does not lose its value over different function calls, so you can use it to control what happen inside functions over calls without using global variables.

Hope that helps.
February 16, 2013
On Thursday, 14 February 2013 at 16:57:17 UTC, Andrea Fontana wrote:
> Maybe you can write 2 different callbacks, one with if, one without and switch between them.

I like that idea.  But it is less elegant.  For example, for a timer callback, I may have to restart the timer with a new callback function.  Instead of a single callback, if it is a event subscription, other subscribers will be affected.

> Maybe with a compile-time code generation to avoid code repetitions...

I am looking for a more generic solution.  It should work with within a loop also.  Just for the sake of achieving it I will have to put those statements in a function, call it with function pointer, etc.

while(true)
{
   ...
   Statement_1;
   if(i == MY_MAGIC_NUMBER)
   {
      //done with this.
   }
   Statement_3;
   ...
}

> Just for a int comparison or is it a different long operation?
:)  you will ask me to short cut with a simple condition.

Thanks,
Gopan
February 16, 2013
On Friday, 15 February 2013 at 09:02:06 UTC, Diego wrote:

> You can use static variables inside that function:
>
> void
> TimerCallback(int number) {
>     statement_1;
>
>     static bool i_found_my_magic_number = false;
>
>     if(!i_found_my_magic_number && number == MY_MAGIC_NUMBER) {
>         i_found_my_magic_number = true;
>         // Do what you need.
>     }
>
>     statement_3;
> }
>
> Static variables does not lose its value over different function calls, so you can use it to control what happen inside functions over calls without using global variables.
>
> Hope that helps.

Dear Diego,

Thanks for caring to reply.

In fact, it is not a business requirement or something like that.  My question is purely on academic interest.
The if_condition being costly is not exaclty what I want to escape from.  I am thinking why I am forced to execute the condition, when I know that I will not be benefited.

Thanks,
Gopan.
February 16, 2013
On Thursday, 14 February 2013 at 13:29:07 UTC, John Colvin wrote:

>
> Not internally to the function, no.
>
> In truth, there's no need to do this. Branch prediction (http://en.wikipedia.org/wiki/Branch_predictor) should reduce the cost hugely.
Thank you for the link.  I will see this and come back.

> Also, a comparison is only going to be 1 cycle, saving a single cycle per second is irrelevant.
For iterating through a ranges of indices in a circular way, I have seen people coding like

int i=0;
while(true)
{
    ...
    i = (i+1)%10;	
}

People argue i = (i+1)%10 is less costly to the combination below.
++i;
if(i==10)
    i = 0;

If the comparison instruction takes only one cycle, how is this argument correct?  Please let me know if that argument is incorrect.

Thanks,
Gopan.
February 16, 2013
Let me ask the question more specifically, with an example of assembly version.
Consider the function below.

void Test()
{
    int x, y, z;

    x = 1;
    if(x==1)
        y=2;
    else
        y=3;
OtherStuff:
    z = 4;
}
---------------
    x = 1;
012313BE  mov     dword ptr [x],1
    if(x==1)
012313C5  cmp     dword ptr [x],1
012313C9  jne     Test+34h (12313D4h)
        y=2;
012313CB  mov     dword ptr [y],2
    else
012313D2  jmp     OtherStuff (12313DBh)
        y=3;
012313D4  mov     dword ptr [y],3
OtherStuff:
    z = 4;
012313DB  mov     dword ptr [z],4


The assembly instruction corresponding to 'if(x==1)' is
012313C5  cmp     dword ptr [x],1

So, if I am able to change the instruction at this address during run-time to
012313C5  jmp     OtherStuff (12313DBh)

Then, I will be able to permanently skip the condition checking.  Right?
Why is this not possible?

All the languages I have heard about allow the programmer to change only the data in memory; not the instructions.  The programmer's thought process is controlled by this idea, subconsciously.
Why can't we change the instructions at runtime?  Is there any fundamental issue with that?
Is it possible to do it through direct assembly coding?

Thanks,
Gopan


February 16, 2013
On Saturday, 16 February 2013 at 17:03:30 UTC, Gopan wrote:
> On Thursday, 14 February 2013 at 16:57:17 UTC, Andrea Fontana wrote:
>> Maybe you can write 2 different callbacks, one with if, one without and switch between them.
>
> I like that idea.  But it is less elegant.  For example, for a timer callback, I may have to restart the timer with a new callback function.  Instead of a single callback, if it is a event subscription, other subscribers will be affected.
>
>> Maybe with a compile-time code generation to avoid code repetitions...
>
> I am looking for a more generic solution.  It should work with within a loop also.  Just for the sake of achieving it I will have to put those statements in a function, call it with function pointer, etc.
>
> while(true)
> {
>    ...
>    Statement_1;
>    if(i == MY_MAGIC_NUMBER)
>    {
>       //done with this.
>    }
>    Statement_3;
>    ...
> }
>
>> Just for a int comparison or is it a different long operation?
> :)  you will ask me to short cut with a simple condition.
>
> Thanks,
> Gopan

for a loop:

while(true)
{
    Statement_1;
    if(magic)
    {
        //do something with magic
        Statement_2;
        break;
    }
    Statement_2;
}

while(true)
{
    Statement_1;
    Statement_2;
}

Simple (assuming that the break in the if statement is the only way out of the loop).

The code repetition can be easily removed by making Statement_1 and Statement_2 mixins.

Remember that D is a compiled language, you can't change the instructions at runtime so there is no way to edit out the if statement at a runtime-dependant time. You have to specify a whole new code path to follow (i.e. the second while loop).
February 16, 2013
On 2/16/13 12:21 PM, Gopan wrote:
> For iterating through a ranges of indices in a circular way, I have seen
> people coding like
>
> int i=0;
> while(true)
> {
> ...
> i = (i+1)%10;
> }
>
> People argue i = (i+1)%10 is less costly to the combination below.
> ++i;
> if(i==10)
> i = 0;
>
> If the comparison instruction takes only one cycle, how is this argument
> correct? Please let me know if that argument is incorrect.
>
> Thanks,
> Gopan.

The general argument is that code with branches may be slower than straight-line code on superscalar architectures. In this particular case the test-based code is likely to be cheaper, which can be easily shown by profiling. For details paste this:

uint fun1(uint x) {
  return (x + 1) % 10;
}

uint fun2(uint x) {
  return x == 10 ? 0 : x + 1;
}

into http://d.godbolt.org and take a look at the generated code. It contains no jumps.


Andrei