Computer Science Canada

[Tutorial] Processes Part 2 – Normalizing Execution

Author:  Tony [ Fri Mar 04, 2005 3:38 pm ]
Post subject:  [Tutorial] Processes Part 2 – Normalizing Execution

Processes Part 2 - Normalizing Execution
In the <a href="http://www.compsci.ca/v2/viewtopic.php?t=7957">previous tutorial</a> I covered the basics of using processes in Turing. This is an in depth view and implementation of their functionality.

The idea behind processes is to create a concurrent system - a program that would have multiple processes running in parallel and accomplish different tasks closely to one another. This by no means speeds anything up. It is better to think of it as spreading the CPU time over more than one task, so instead of having player1 move and then wait for player2 to do its calculations, both processes take turns processing bits and wait for each other. In a perfect world, both would run in parallel, but alas it is not the default case.

Turing:

process player (ID : int)
    var x : real := 0
    loop
        Draw.FillBox (0, 10 + ID * 10, round (x), 15 + ID * 10, ID*5)
        x += 0.1 %decrease the value to slow down
        if x >= maxx then
            put "player", ID, "::", Time.Elapsed
            return
        end if
    end loop
end player

for i : 1 .. 20
    fork player (i)
end for

The above code races 20 processes against each other.
Posted Image, might have been reduced in size. Click Image to view fullscreen.

In a sample case (x += 0.01), the fastest process has finished half a second before the slowest one (32797 vs 33219), but try it out for yourself. Deviations accumulate over time. This sample 30 second run yielded 1.3% difference. Divergence increases with the number of processes present. Although you might think that 1.3% is insignificant, that advantage will be amplified if one player is 1% faster, 1% stronger, 1% more accurate, and 1% some other way better than the next guy. And this is just with 20 processes. Increased number of objects will make calculations very inconsistent.

A way to normalize all of those processes is needed.

I was going to go for something complex, but the accident solution works quite well for now.

Turing:

loop
    exit when false
end loop

That's right. Stick that at the end of your program. Virtually no CPU time is lost since it's a single bitwise comparison, but processes are put in place. I cannot explain this yet, just take a look yourself.

Turing:

process player (ID : int)
    var x : real := 0
    loop
        Draw.FillBox (0, 10 + ID * 10, round (x), 15 + ID * 10, ID*5)
        x += 0.1 %decrease the value to slow down
        if x >= maxx then
            put "player", ID, "::", Time.Elapsed
            return
        end if
    end loop
end player

for i : 1 .. 20
    fork player (i)
end for

loop
    exit when false
end loop

Posted Image, might have been reduced in size. Click Image to view fullscreen.
The difference between fastest and slowest processes has be reduced 10 times and overall (average time between the two extremes) was faster for a sample normalized process group.

Author:  ssr [ Fri Mar 04, 2005 11:35 pm ]
Post subject: 

ooo
tnx for the tutorial
Very Happy 8)

Author:  Shyfire [ Tue Apr 19, 2005 9:46 am ]
Post subject: 

i still dont see how that normalizes the processes¿


i'm lost¿¿¿¿¿

Author:  Tony [ Tue Apr 19, 2005 12:27 pm ]
Post subject: 

fatboi wrote:
i'm lost¿¿¿¿¿

you must have forgotten to try out the code. I attached an additional screenshot for you.

Author:  MysticVegeta [ Sat May 14, 2005 10:48 am ]
Post subject: 

fork process1 and process2

turing crashes

Author:  Cervantes [ Sat May 14, 2005 11:46 am ]
Post subject: 

Must you post this everywhere? Really, it's not that amazing. Furthermore, I don't even get the crashing.

Author:  [Gandalf] [ Sat May 14, 2005 3:38 pm ]
Post subject: 

Amazing... I must have overlooked this tutorial before, it really helps.

I guess process' are not so evil anymore, are they Smile

Author:  Cervantes [ Sat May 14, 2005 4:15 pm ]
Post subject: 

[Gandalf] wrote:
I guess process' are not so evil anymore, are they Smile

A minor adjustment in emphasis:
I guess processes are not so evil anymore, are they
----
They're not as bad, if you use this technique. But the fact still remains that you don't know how your program will execute.
The big downside, however, to this is that it sort of limits you to ONLY using processes. I say sort of, because the only way that I can find to get this to work nicely is to have the only exit statement as exit when false. That is, you can't exit your loop. If you try to add other conditions, things go wrong with the execution timings.
Let's have some code:
Turing:

var x := 0.0

process player (ID : int)
    var x : real := 0
    loop
        Draw.FillBox (0, 10 + ID * 10, round (x), 15 + ID * 10, ID * 5)
        x += 0.1 %decrease the value to slow down
        if x >= maxx then
            put "player", ID, "::", Time.Elapsed
            return
        end if
    end loop
end player

for i : 1 .. 20
    fork player (i)
end for

loop
    Draw.FillBox (0, 10 + 21 * 10, round (x), 15 + 21 * 10, 21 * 5)
    x += 0.1     %decrease the value to slow down
    if x >= maxx then
        put "player", 21, "::", Time.Elapsed
    end if
    exit when false %or x >= maxx   %Try uncommenting the second condition.  See how player 21 (the one not in a process) loses?
end loop


EDIT: Actually, it seems that putting the exit inside the if x >= maxx then statement of the main loop works fine. Alright, so processes are now more clunky, though they seem to work decently. I still say they should be avoided in most cases.

Author:  Anonymous [ Mon Jun 05, 2006 11:07 pm ]
Post subject: 

You guys are learning to control processes =) That's sweet.

Author:  Cervantes [ Wed Jun 07, 2006 11:33 am ]
Post subject: 

vahnx wrote:
are learning

learned. Wink

Though it needs to be understood that the basic principle of processes means your giving away part of the control flow of your program to the operating system. There are many times that people use processes when they are not necessary. These situations should generally be avoided.

Author:  wtd [ Wed Jun 07, 2006 12:30 pm ]
Post subject: 

In other words:

Know the language. If you know it. then you'll know when it's appropriate to use its various capabiliies.

By the same logic, if you do not know how to appropriately apply language capabilities, then you do not know the language.

Author:  Reality Check [ Sat Jun 10, 2006 7:25 pm ]
Post subject: 

Wait so using that bit of cold you told us, we can use processes now? Does this fix everything or is it just a minor achievment?

Author:  [Gandalf] [ Sat Jun 10, 2006 7:39 pm ]
Post subject: 

It gives you better control of processes when you absolutely need to use them. It doesn't change the fact that in most situations processes are not the best solution to a problem.

Author:  Reality Check [ Sat Jun 10, 2006 7:51 pm ]
Post subject: 

would I be better off putting it all in a loop and calling each thing in procedure?

so:

code:

var x, y, b : int

proc procedure1
drawoval (x, y, z, q, black)
end procedure1

proc procedure2
drawoval (x, y, z, q, green)
end procedure2

loop
     Mouse.Where (x, y, b)
     if b = 1 then
          procedure1
     elsifif b = 0 then
          procedure2
     end if
end loop


Or would it be better to simply draw the ovals inside the ifs themselves? Ofcourse, it will be much more complicated than that with more lines in the 'if' but thats a simplified version. I'm doing a paint program and I read why processes are bad. However, does it matter if they don't occur at the same exact time with a paint? I mean if it were a game where there is collision detect and lives and levels all happening at once than I'd see why that extra bit counts. I posted my paint in the source code section in case you don't get what I mean.

Author:  Cervantes [ Sat Jun 10, 2006 8:04 pm ]
Post subject: 

There is no reason to use processes for a paint type program.

In your example, your procedures are redundent. They do almost exactly the same thing. The minor difference between them can easily be achieved through parameter passing. Furthermore, you shouldn't be using global variables (x, y, z, q) to draw the ovals. Rather, pass them into the procedure.


There seems to be this idea that a procedure is the opposite of a processes; that if you don't use a process, you've got to use a procedure.

Here's the deal. A process allows you to do two tasks simultaneously (though not really, as outlined in these tutorials on processes and why they should be avoided). Chances are, your processes will have loops of their own. So now you can run two loops at the same time (sort of).

If you are going to do this without processes, it means you're doing everything in one loop. This does not mean you have to use procedures. It just means you are only using one loop (not talking about nested loops here -- that's irrelevant to this discussion). Procedures will definately make your loop much more consise and understandable, but they are not necessary. Procedures are just a tool to make this task easier.

Author:  Reality Check [ Sat Jun 10, 2006 8:18 pm ]
Post subject: 

no my (x,y,q,z) was just an example. Its not actually like that. Obviously if the difference in the 'ifs' was so small I'd just draw it in the actual 'if' itself. However, when I'm distinguishing between tools as in painting, using the pencil, or drawing circles, the procedure is good for organization. I just took out all processes in my program and have one big loop, each tool is called by a procedure and my BIG loop is not so big anymore. I see what you all mean by not using processes, it does make it smoother and although the difference may not be huge, it makes for an all-round nicer program.

Author:  Cervantes [ Sat Jun 10, 2006 8:34 pm ]
Post subject: 

Reality Check wrote:
no my (x,y,q,z) was just an example. Its not actually like that.

What's the point of posting an example if it is flawed and is not an accurate representation? Wink

Glad to hear you've switched to a process-free paint.


: