Programming C, C++, Java, PHP, Ruby, Turing, VB
Computer Science Canada 
Programming C, C++, Java, PHP, Ruby, Turing, VB  

Username:   Password: 
 RegisterRegister   
 [Tutorial] Benchmarking Draw.ThickLine with Turing
Index -> Programming, Turing -> Turing Tutorials
View previous topic Printable versionDownload TopicRate TopicSubscribe to this topicPrivate MessagesRefresh page View next topic
Author Message
Tony




PostPosted: Mon Jul 10, 2006 11:48 pm   Post subject: [Tutorial] Benchmarking Draw.ThickLine with Turing

Benchmarking with Turing

wikipedia.org wrote:

In computing, a benchmark is the result of running a computer program, or a set of programs, in order to assess the relative performance of an object, by running a number of standard tests and trials against it.

What is the best way of performing a certain action? On an introductory level it doesn't matter - whatever works will suffice. "Premature Optimization... Don't!" - wtd.

Though when we do get to that end.. when everything works, but we want to make it faster.. how do we judge the performance?

It is assumed that you know your BigO()s, your algorythms are efficient and we are concerned with picking one function over another on the same order of complexity.

A question has been brought up in [Turing Help] on the execution time of Draw.ThickLine.
Mazer wrote:
But also, making your own Draw.ThickLine() probably won't give you results as good as the one Turing already has, speed-wise.

Windsurfer wrote:
Why not? I read somewhere that a lot of turing is made using turing code, so why can't i just tweak it a bit and have it just as fast? Like, sure, maaaybe they coded Draw.ThickLine() in assembly or C, but I ighly doubt it, especially considering how it's a fairly new addition.


I wanted to find out.

The Set Up
{

Turing:

var x1,x2,y1,y2:int
var t_start, t_end:int

%test out original

t_start := Time.Elapsed

for i:1..100
    x1 := Rand.Int(0,300)
    x2 := Rand.Int(0,300)
    y1 := Rand.Int(0,300)
    y2 := Rand.Int(0,300)
    Draw.ThickLine(x1,y1,x2,y2,5,black)
    Draw.ThickLine(x1,y1,x2,y2,3,grey)
end for

t_end := Time.Elapsed - t_start

locate(1,1)
put t_end

The set up usually takes the following form:
code:

variable declarations
and other overhead

start timer

loop

end timer

display results

The larger the test loop - the better average result. We are trying to average out whatever noise and spikes that might have occured during the testing. It is also important to isolate the timing as close to the function we're measuring as possible.

If using Rand.Int, it is essential to have a large enough sample set to normalize the outcome. 100 samples is a fairly poor choice for the above test, you would normally want something that runs for at least a second or more, but the next comparison test is considerably slower and 100 samples is sufficient to demonstrate the difference.
}
Alternate Function
{

Turing:

proc MyLine(x1,y1,x2,y2,w,c:int)
    var a:real
    var width:int := w div 2

    %calculate angle of the line
    if (x2-x1) = 0 then
        if y2>y1 then
            a:=PI/2
        else
            a:=PI*1.5
        end if
    else
        a:=arctan((y2-y1)/(x2-x1))
        if x2 < x1 then
            a += PI
        end if
    end if

    %for each point on the line
    for i:1..round(Math.Distance(x1,y1,x2,y2))
        Draw.FillOval(round(x1+i*cos(a)),round(y1+i*sin(a)), width, width, c)
    end for

end MyLine

This is my attempt at drawing a ThickLine, by constructing it out of circles. A faster approach would have been to draw a number of lines and just round off the corners, but some pixels were being skipped at certain angles, so the function didn't behave the same.

The benchmark test should be performed right after the original, hoping that the system is in a relativly same state of load.
Turing:

t_start := Time.Elapsed
for i:1..100
    x1 := Rand.Int(300,600)
    x2 := Rand.Int(300,600)
    y1 := Rand.Int(0,300)
    y2 := Rand.Int(0,300)
    MyLine(x1,y1,x2,y2,5,black)
    MyLine(x1,y1,x2,y2,3,grey)
end for
t_end := Time.Elapsed - t_start
locate(1,10)
put t_end

}
Some Conclusions

Posted Image, might have been reduced in size. Click Image to view fullscreen.
61 against 1620 - it's not even a contest. Turing's native Draw.ThickLine is much faster to draw. On the other hand I notice that my function results in a more vivid black outline Wink



ss_benchmark_thickline.GIF
 Description:
 Filesize:  35.42 KB
 Viewed:  9902 Time(s)

ss_benchmark_thickline.GIF


Latest from compsci.ca/blog: Tony's programming blog. DWITE - a programming contest.
Sponsor
Sponsor
Sponsor
sponsor
Cervantes




PostPosted: Tue Jul 11, 2006 7:47 am   Post subject: (No subject)

Nice, Tony.

Though I think it would be a good idea to remove the Rand.Int's from the for loop. Just hardcode the coordinates so the line draws over itself every time. This doesn't affect the drawing speed, so we can safely factor out those Rand.Int's that are common to both tests.
Windsurfer




PostPosted: Wed Jul 12, 2006 9:20 pm   Post subject: Who said this was a test?

Wink I must say, drawing circles? That's no way to draw a line! Razz

Okay, so i made another procedure. It's a little less than half of turing's speed (though it can be sped up to faster than turing at the loss of accuracy!)
I'm still working on it. Maybe I can improve it some more.

code:

procedure DrawFillPoly_Int (x1 : array 1 .. * of int, y1 : array 1 .. * of int, clr : int)
    if upper (x1) > upper (y1) then %what is the upper bound
        Draw.FillPolygon (x1, y1, upper (y1), clr)
    else
        Draw.FillPolygon (x1, y1, upper (x1), clr)
    end if
end DrawFillPoly_Int


procedure DrawThickLine (x1, y1, x2, y2, width : real, clr : int)
    %find angle
    const delta_y := (y2 - y1)
    var angle : real
    if x1 <= x2 then
        angle := arcsind (delta_y / sqrt ((x2 - x1) ** 2 + delta_y ** 2)) + 90
    else
        angle := 180 - arcsind (delta_y / sqrt ((x2 - x1) ** 2 + delta_y ** 2)) + 90
    end if
    var xp : array 1 .. 20 of int
    var yp : array 1 .. 20 of int
    %set points
    for lp : 0 .. 9
        xp (lp + 1) := round (x1 + cosd (angle + lp * 20) * width)
        yp (lp + 1) := round (y1 + sind (angle + lp * 20) * width)
    end for
    for lp : 9 .. 18
        xp (lp + 2) := round (x2 + cosd (angle + lp * 20) * width)
        yp (lp + 2) := round (y2 + sind (angle + lp * 20) * width)
    end for
    DrawFillPoly_Int (xp, yp, clr)
end DrawThickLine

var last_time : real
var test1, test2 : string
put "Running... time is in miliseconds..."

%These values are completly arbitrary

var mouse_x, mouse_y, button : int
loop
    Mouse.Where (mouse_x, mouse_y, button)
    DrawThickLine (120, 120, mouse_x, mouse_y, 30, black)
    delay (40)
    cls
    exit when button = 1
end loop


loop
    last_time := Time.Elapsed
    for lp : 1 .. 10000
        Draw.ThickLine (20, 20, 200, 200, 60, black)
    end for
    test1 := "using turing's built-in: " + realstr (Time.Elapsed - last_time, 5)

    last_time := Time.Elapsed
    for lp : 1 .. 10000
        DrawThickLine (120, 20, 300, 200, 30, black)
    end for
    test2 := "using my procedure:      " + realstr (Time.Elapsed - last_time, 5)
    cls
    put test1
    put test2
end loop


Using this level of accuracy:
Turing : 1068
Me : 1996

I'm catching up! Razz
zylum




PostPosted: Thu Jul 13, 2006 12:29 am   Post subject: (No subject)

the whole point of this tutorial was how to bench mark, not how to draw a thick line efficiently. besides, here's one that draws thick lines more like Turings built in procedure as well as does it faster than yous Laughing

code:
proc DrawThickLine (x1, y1, x2, y2, w, c : int)

    var x : array 1 .. 4 of int
    var y : array 1 .. 4 of int

    var m := sqrt ((x2 - x1) ** 2 + (y2 - y1) ** 2)

    var i := (y2 - y1) / m
    var j := (x2 - x1) / m

    var width := w / 2

    x (1) := round (x1 + i * width)
    x (2) := round (x1 - i * width)
    x (3) := round (x2 - i * width)
    x (4) := round (x2 + i * width)

    y (1) := round (y1 - j * width)
    y (2) := round (y1 + j * width)
    y (3) := round (y2 + j * width)
    y (4) := round (y2 - j * width)

    Draw.FillPolygon (x, y, 4, c)
    Draw.FillOval (x1, y1, round (width - 1), round (width - 1), c)
    Draw.FillOval (x2, y2, round (width - 1), round (width - 1), c)

end DrawThickLine
Windsurfer




PostPosted: Fri Jul 14, 2006 7:11 pm   Post subject: Not true!

zylum wrote:
the whole point of this tutorial was how to bench mark, not how to draw a thick line efficiently. besides, here's one that draws thick lines more like Turings built in procedure as well as does it faster than yous Laughing


I know it's a tutorial, but it is an offshoot of a question i asked earlier. Since this topic is more relevant, I decided to post here.
On your claim that yours is faster:
Not true! I benchmarked using my program, and the timing results are :
Yours : 2860
Mine : 1906

These numbers don't vary by any more than 100 in either direction, btw.
[Gandalf]




PostPosted: Fri Jul 14, 2006 7:30 pm   Post subject: (No subject)

Before you get into a fight about whose function is faster, may I refer you a previous post of mine showing how inaccurate benchmarking in Turing can be: here. Wink

Now, that may not be the sole reason for the difference in your results, but it's good to keep in mind.
Windsurfer




PostPosted: Fri Jul 14, 2006 8:29 pm   Post subject: (No subject)

Gandalf, I completly agree with you, which is why i stated about how much the variance that i observed was.

I would also like to say that after further testing, I have discovered that zylum's procedure can be faster when the thickness of the line is 20 or less, but mine wins at larger numbers. I believe that may be due to the differences in time that Draw.FillOval has when dealing with different sizes (as opposed to polygons, which seem to have a more uniform resource use).
I suppose if i wanted to make my procedure better, i would have some sort of equation that relates the size of the thick line to the number of sides on my polygon. (right now it's 20 sides, but if i reduce it to 4 sides, it beats even turings built-in)
[Gandalf]




PostPosted: Fri Jul 14, 2006 8:45 pm   Post subject: (No subject)

Windsurfer wrote:
Gandalf, I completly agree with you, which is why i stated about how much the variance that i observed was.

Indeed, only there is another factor that you hadn't considered. In my linked post it became obvious that whichever test was started first would run longer or equally as long as the other test. Did you try switching the order in which you tested the procedures?

Of course, I digress. The differences in how the two lines are drawn and the conditions which they are drawn in have a much larger effect on the results of the benchmark than these random deviations.
Sponsor
Sponsor
Sponsor
sponsor
Windsurfer




PostPosted: Fri Jul 14, 2006 10:14 pm   Post subject: (No subject)

AHAHAHA!!Laughing Laughing Laughing

OKAY! I was messing with that timing program you made, and i was thinking "this can't be right... wow turing sucks" so i flip the order of the tests, unconviced that order should have anything to do with it. "What the hell???" I get the same results. timeB wins 40 to 60 even. 0 to timeB. I then also make this whole new part of code (thinking maybe there's something else about the code that i'm missing) that randomises the order. SAME RESULTS! 40 to 60 about, plus 0 for timeB. It made NO sense. I was thinking Gandalf was really a wizard.

SO! I keep looking at your code, very conviced that there's something wrong with it... like, HOW can timeB NEVER beat timeA?! i couldn't understand.
Then I found it Laughing Laughing

code:

    put "Test finished..."
    var timeALonger, timeBLonger, timesEqual : int := 0
    for i : 1 .. upper (timeA)
        if timeA (i) > timeB (i) then
            timeALonger += 1

% -------   Right here --------
        elsif timeB (i) > timeB (i) then

            timeBLonger += 1
        else
            timesEqual += 1
        end if
    end for
    put "Time A longer: ", timeALonger / upper (timeA) * 100, "%"
    put "Time B longer: ", timeBLonger / upper (timeB) * 100, "%"
    put "Times equal: ", timesEqual / upper (timeA) * 100, "%"


Well THERE you go! Comparing timeB to timeB! Of course it can never be greater!

I fixed it, and what do you know? i get the predicted and theoretical results.

(sorry for bursting your bubble Gandalf)
Windsurfer




PostPosted: Fri Jul 14, 2006 10:15 pm   Post subject: (No subject)

Sorry that last post was really off topic, but i felt I had to share it, and the old forum that had the original code was locked. Sad
[Gandalf]




PostPosted: Fri Jul 14, 2006 10:39 pm   Post subject: (No subject)

It's not off topic on a Tutorial about benchmarking. A double post, on the other hand is something to be shamed. Wink

Anyway, dang that was a stupid mistake on my part. Everyone makes mistakes though, especially as simple as mistyping A as B heh. You can never be sure with Turing either.

And who says I'm not a wizard? Thinking
Display posts from previous:   
   Index -> Programming, Turing -> Turing Tutorials
View previous topic Tell A FriendPrintable versionDownload TopicRate TopicSubscribe to this topicPrivate MessagesRefresh page View next topic

Page 1 of 1  [ 11 Posts ]
Jump to:   


Style:  
Search: