|
From: David S. <dsc...@vi...> - 2002-06-21 19:46:15
|
First of all, keep in mind that there are two rates involved:
- How many times per second VPython's background rendering thread can
draw the scene with OpenGL. (the "frame rate")
- How many times per second your while loop executes ("loop rate" or
"update rate")
These two numbers can be entirely different. Your program measures the
second, which is also what rate() controls. There is no way to change
the rendering frame rate in VPython (except to buy a faster computer :),
and VPython keeps rendering the screen even when there is no mouse input
and no updates by the program.
Now, what rate() does is fairly simple. It could be written in Python
something like this (with some error checking and so on omitted):
origin = time.time()
def rate(N):
global origin
delay = 1.0 / N
float t = delay - (time.time() - origin)
if t > 0.010:
time.sleep(t)
else:
while (delay - (time.time() - origin) > 0):
pass
origin = time.time()
Essentially, it just sleeps or wastes CPU time until the previous
iteration of the loop took at least 1/N seconds.
The reason this can still have an effect when your "loop rate" is less
than N, because your loop will not execute in exactly the same wall
clock time each time, and rate() does not attempt to average across
iterations.
For example, let's say N = 50, and your loop (without the call to
rate()) takes 10ms for every even iteration and 30ms for every odd
iteration. On each even iteration, rate() will sleep for 10ms, so that
that iteration takes 20ms. On odd iterations it will not sleep at all.
The net effect is that the frame rate changes from 50 (20ms average) to
40 (25ms average).
Another factor is that the operating system's Sleep() function is
extremely inaccurate. The time slices used by Windows are often on the
order of 15ms, which is quite a large margin of error in the type of
test you are doing. This likely accounts for the "stairstepping" effect
you are seeing, and it might also account for some of the variation.
The reason the function above uses an inefficient spin loop for sleeps
less than 10ms is that for such lengths of time, the average time taken
by a Sleep can be a large factor different than the number passed to it.
Hope that helps. I haven't actually done any experiments to confirm
these hypotheses, so take them with a grain of salt.
Dave
> -----Original Message-----
> From: vis...@li...
> [mailto:vis...@li...] On
> Behalf Of Gary Strangman
> Sent: Friday, June 21, 2002 1:58 PM
> To: Bruce Sherwood
> Cc: vis...@li...
> Subject: Re: [Visualpython-users] rate() function
>
>
>
> For what it's worth, this _only_ happens when the computer
> can't keep up (like, when drawing 500 background objects).
> When the computer is able to keep up, a rate(n) gives an
> actual framerate of n (or very slightly less, thanks to
> random background processes.
>
> > Many thanks for offering this analysis tool. It sure looks like
> > something
> > is very wrong with the rate machinery. A quick look at the
> Visual code
> > indicates that rate ought to work fine, but it most
> assuredly isn't working
> > fine, as you show conclusively.
> >
> > Bruce Sherwood
> >
> > At 11:35 AM 02/06/21 -0400, Gary Strangman wrote:
> >
> > >Hi all,
> > >
> > >This might be a bit off-topic--perhaps hardware
> related(?)--but does
> > >anyone know exactly what happens when you pick value of N
> such that
> > >your computer can't handle a given "rate(N)" visualpython
> statement?
> > >Do frames get dropped? Or is it dependent on one's
> graphics card, or
> > >screen refresh rates, or openGL implementation? Using the program
> > >below, my _actual_ framerate increases as a stair-stepped
> function of
> > >the _specified_ framerate. What I find odd is that the _actual_
> > >framerate does keep on increasing. That is, rate(50)
> doesn't give me
> > >a 50Hz frame rate, but (according to my loop anyway) using
> rate(100)
> > >gives me a better than 50Hz frame rate. I would think that
> the actual
> > >framerate should increase linearly to the point where
> one's computer
> > >is maxed out, and then plateau indefinitely. Apparently
> that's naive.
> > >Any ideas? I've tested this on both a couple machines (though both
> > >are portables with, of course, LCD monitors).
> > >
> > >Thanks in advance for any guesses (or better yet, answers) ...
> > >
> > >Gary
> > >strang-@at...@-n...
> > >
> > >--- cut here ---
> > >
> > >from visual import *
> > >import time, sys, whrandom
> > >
> > >scene.title = "Speed test"
> > ># Create 2 frames
> > >fworld = frame(pos=(0,0,0))
> > >ftarget = frame(frame=fworld,pos=(0,0,0))
> > >ftarget.pos = (0,0,0)
> > >fworld.pos = (0,0,10)
> > >
> > ># Draw some main objects
> > >body = cylinder(frame=ftarget, pos=(0,0,0), axis=(0,0,0.35),
> > >radius=1,
> > >color=(0,0,1),visible=1)
> > >pin = cylinder(frame=ftarget, pos=(0,1,0), axis=(0,1,0), radius=1,
> > >color=(1,1,1),visible=1)
> > >pinball = sphere(frame=ftarget, pos=(0,-1,0), radius=1,
> > >color=(1,1,0),visible=1)
> > >topbox = box(frame=ftarget, pos=(0,0.34,0.20), axis=(0,1,0),
> > >length=0.2,width=0.1,height=0.1, color=(1,0,0),visible=1)
> > >horizon = cylinder(frame=ftarget, pos=(-5,2,0),
> axis=(10,0,0), radius=1,
> > >color=(0,1,0),visible=1)
> > >
> > >xINC = 0
> > >yINC = 0.001
> > >zINC = 0.003
> > >rollINC = 0
> > >pitchINC = 0
> > >yawINC = 0
> > >scene.autoscale = 0
> > >NUM_DOTS = 500
> > >RADIUS = 120
> > >rad = 0.4
> > ># now draw background objects
> > >for i in range(0, NUM_DOTS):
> > > x = whrandom.random() - 0.5
> > > y = whrandom.random() - 0.5
> > > z = whrandom.random() - 0.5
> > > length = math.sqrt(x*x + y*y + z*z)
> > > x = x / length * RADIUS
> > > y = y / length * RADIUS + 1.8
> > > z = z / length * RADIUS
> > > sphere(pos=(x,y,z),radius=rad)
> > >
> > >frameratelist = []
> > >for framerate in range(10,250,1):
> > > framecount = 0
> > > starttime = time.clock()
> > > while framecount<5*framerate: # integrate over,
> theoretically, 5sec
> > > rate(framerate)
> > > framecount += 1
> > > fworld.pos.x -= xINC
> > > fworld.pos.y -= yINC
> > > fworld.pos.z = framecount*zINC
> > >
> > > # Rotate "CAMERA" (actually, move whole _world_
> around camera)
> > > fworld.rotate(angle=pitchINC, axis=(1,0,0),
> > > origin=scene.mouse.camera)
> > > fworld.rotate(angle=yawINC, axis=(0,1,0),
> origin=scene.mouse.camera)
> > > fworld.rotate(angle=rollINC, axis=(0,0,1),
> origin=scene.mouse.camera)
> > > endtime = time.clock()
> > > print "Rate(%i): %i frames in %2.2f sec = %2.2f frames/sec" %
> > > (framerate, framecount, (endtime-starttime),
> framecount/(endtime-starttime))
> > > frameratelist.append((framerate, framecount,
> (endtime-starttime),
> > > framecount/(endtime-starttime)))
> > >
> > >
> > >
> > >-------------------------------------------------------
> > >Sponsored by:
> > >ThinkGeek at http://www.ThinkGeek.com/
> > >_______________________________________________
> > >Visualpython-users mailing list
> > >Vis...@li...
> > >https://lists.sourceforge.net/lists/listinfo/visualpython-users
> >
> >
> >
>
>
>
> -------------------------------------------------------
> Sponsored by:
> ThinkGeek at http://www.ThinkGeek.com/
> _______________________________________________
> Visualpython-users mailing list
> Vis...@li...
> https://lists.sourceforge.net/lists/listinfo/visualpython-users
>
|