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@-nmr.mgh.harvard.edu > > > > > >--- 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 > |