Re: [pygame] pygame.display.flip slow
Hi, Thanks again for the answers. Both machines are running Fedora Linux. Both are using X11 and the nvidia drivers, but the drivers are different versions (older graphics card in machine B). I'll look at the settings to see if I can figure out the difference. I'll try to find out On Thu, Feb 20, 2020 at 10:30 PM Greg Ewing wrote: > On 20/02/20 8:57 am, Nuno Maltez wrote: > > when I run my test program, Machine B reports FPS > 200, and > > pygame.display.flip taking 0.002 per call, > > while machine A reports FPS < 60, and pygame.display.flip taking 0.016 > > per call. > > This looks to me like machine A is synchronising its flips > with the monitor's refresh rate, but machine B is not. Why > that would be when you're creating the surface with the same > flags I don't know. Maybe a difference in the display > driver? > > -- > Greg >
Re: [pygame] pygame.display.flip slow
On 20/02/20 8:57 am, Nuno Maltez wrote: when I run my test program, Machine B reports FPS > 200, and pygame.display.flip taking 0.002 per call, while machine A reports FPS < 60, and pygame.display.flip taking 0.016 per call. This looks to me like machine A is synchronising its flips with the monitor's refresh rate, but machine B is not. Why that would be when you're creating the surface with the same flags I don't know. Maybe a difference in the display driver? -- Greg
Re: [pygame] pygame.display.flip slow
Hi, To me, these results suggest that the faster-framerate machine is running with VSync enabled for some reason and the slower-framerate machine is running without. Also, what I said about setting pixels on the CPU still goes, albeit that's not the issue here. Offhand, I would guess that the faster-framerate machine is running Windows, which doesn't enable VSync, and the slower-framerate machine is running something else. But I don't know. In general, faster framerates are pointless (you can't even display them), so one should be satisfied with ~60Hz refresh, and make the logic independent of timestep (locking the framerate to the refresh rate is a *good* thing; the fascination with faster framerates is due to modern video games running <60Hz, or to gamers running >60Hz with tearing (and without VSync).). There are platform-specific ways to disable VSync. It's not even that hard for OpenGL contexts. But it's sortof an X-Y problem that doesn't need solving. Ian
Re: [pygame] pygame.display.flip slow
Hi, Thanks for the quick feedback, and apologies if my little program caused some confusion - I wrote it quickly to highlight an issue, but I guess I should have included some results from another machine for comparison. I made some improvements based on Ian's suggestions: 1. I don't average anything, just output the recorded fps values 2. I removed the argument to tick() - this actually helps to showcase the issue I ran the code (pasted below) on two machines: Machine A: Intel(R) Core(TM) i7-5930K CPU @ 3.50GHz Python 3.7, Pygame1.9.6 Machine B: Intel(R) Core(TM) i7-4650U CPU @ 1.70GHz Python 3.7, Pygame1.9.6 The first benchmark on google results shows A should be significantly faster than B https://cpu.userbenchmark.com/Compare/Intel-Core-i7-4650U-vs-Intel-Core-i7-5930K/m6364vs2578 I ran pyperformance ( https://pyperformance.readthedocs.io/usage.html#installation) on both machines and it seems to confirm that. However, when I run my test program, Machine B reports FPS > 200, and pygame.display.flip taking 0.002 per call, while machine A reports FPS < 60, and pygame.display.flip taking 0.016 per call. This puzzles me: I was expecting a result similar to B on both machines, since my loop does nothing - has no game logic, no physics, no image handling. I was wondering if someone has any ideas to help me find out what's wrong with my setup in machine A. Btw, enabling fullscreen does not help, not does changing the display resolution while running in the windowed mode. Both displays are running at 60Hz. MAchine A: $ python fps_test.py pygame 1.9.6 Hello from the pygame community. https://www.pygame.org/contribute.html [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 54.64480972290039, 54.64480972290039, 54.64480972290039, 54.64480972290039, 54.64480972290039, 54.64480972290039, 54.64480972290039, 54.64480972290039, 54.64480972290039, 54.64480972290039, 57.47126770019531, 57.47126770019531, 57.47126770019531, 57.47126770019531, 57.47126770019531, 57.47126770019531, 57.47126770019531, 57.47126770019531, 57.47126770019531, 57.47126770019531, 58.82352828979492, 58.82352828979492, 58.82352828979492, 58.82352828979492, 58.82352828979492, 58.82352828979492, 58.82352828979492, 58.82352828979492, 58.82352828979492, 58.82352828979492, 59.52381134033203, 59.52381134033203, 59.52381134033203, 59.52381134033203, 59.52381134033203, 59.52381134033203, 59.52381134033203, 59.52381134033203, 59.52381134033203, 59.52381134033203, 59.88024139404297, 59.88024139404297, 59.88024139404297, 59.88024139404297, 59.88024139404297, 59.88024139404297, 59.88024139404297, 59.88024139404297, 59.88024139404297, 59.88024139404297, 58.479530334472656, 58.479530334472656, 58.479530334472656, 58.479530334472656, 58.479530334472656, 58.479530334472656, 58.479530334472656, 58.479530334472656, 58.479530334472656, 58.479530334472656, 58.479530334472656, 58.479530334472656, 58.479530334472656, 58.479530334472656, 58.479530334472656, 58.479530334472656, 58.479530334472656, 58.479530334472656, 58.479530334472656, 58.479530334472656, 58.479530334472656, 58.479530334472656, 58.479530334472656, 58.479530334472656, 58.479530334472656, 58.479530334472656, 58.479530334472656, 58.479530334472656, 58.479530334472656, 58.479530334472656, 59.17159652709961, 59.17159652709961, 59.17159652709961, 59.17159652709961, 59.17159652709961, 59.17159652709961, 59.17159652709961, 59.17159652709961, 59.17159652709961, 59.17159652709961] 405 function calls in 1.760 seconds Ordered by: standard name ncalls tottime percall cumtime percall filename:lineno(function) 10.0000.0001.7601.760 :1() 10.0020.0021.7601.760 fps_test.py:11(run) 10.0000.0001.7601.760 {built-in method builtins.exec} 10.0000.0000.0000.000 {built-in method builtins.print} 1001.6440.0161.6440.016 {built-in method pygame.display.flip} 10.0000.0000.0000.000 {method 'disable' of '_lsprof.Profiler' objects} 1000.1140.0010.1140.001 {method 'fill' of 'pygame.Surface' objects} 1000.0000.0000.0000.000 {method 'get_fps' of 'Clock' objects} 1000.0000.0000.0000.000 {method 'tick' of 'Clock' objects} Machine B: $ python fps_test.py pygame 1.9.6 Hello from the pygame community. https://www.pygame.org/contribute.html [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 256.4102478027344, 256.4102478027344, 256.4102478027344, 256.4102478027344, 256.4102478027344, 256.4102478027344, 256.4102478027344, 256.4102478027344, 256.4102478027344, 256.4102478027344, 263.15789794921875, 263.15789794921875, 263.15789794921875, 263.15789794921875, 263.15789794921875, 263.15789794921875, 263.15789794921875, 263.15789794921875, 263.15789794921875, 263.15789794921875, 303.0303039550781, 303.0303039550781, 303.0303039550781, 303.0303039550781, 303.0303039550781, 303.0303039550781, 303.0303039550781,
Re: [pygame] pygame.display.flip slow
Hi, First, there are some problems with this test code: - The first ten framerates will be 0.0 due to what I consider a misfeature in the way pygame reports framerate; this drags down your average. Even if you ran at a nominal 60Hz, the highest reported framerate is going to be 54fps (wherefore, I'm somewhat confused that you say you got 60Hz on a different machine; perhaps you were running a bit faster; e.g. I see 62Hz a lot on certain machines). - Averaging the framerates is a bit problematic because that is a reciprocal measure. It is better to average the frame latencies and then reciprocate that to get the average framerate. - You're attempting to synchronize the framerate to 60Hz, this can cause aliasing issues since pygame is software-backed, not graphics backed, exactly. E.g., if your code is actually 59fps, then the fastest it can update will be 30fps. It would be better to not include the argument to `.tick(...)` at all. Which brings us to the main reason: - Setting millions of pixels is not a job for the CPU; it's a job for the graphics card. However, pygame runs on the CPU. As you observe, larger displays run slower. If you want good refresh-bound performance, you probably want to make a GL context and draw with that, without disabling VSync. This is, in fact, what glxgears does, which is why it's running at a reasonable framerate. Ian
Re: [pygame] pygame.display.flip slow
‐‐‐ Original Message ‐‐‐ On Tuesday, February 18, 2020 3:50 PM, Nuno Maltez wrote: > Hi > I'm experiencing very slow frame rates on a particular set up and need some > help to understand > what may be causing it. > On this machine, the code below has an avg fram rate of around 45fps. > The profiling output is: > > ncalls tottime percall cumtime percall filename:lineno(function) > 1 0.000 0.000 2.015 2.015 :1() > 1 0.001 0.001 2.015 2.015 fps_test.py:11(run) > 1 0.000 0.000 2.015 2.015 {built-in method builtins.exec} > 1 0.000 0.000 0.000 0.000 {built-in method builtins.print} > 1 0.000 0.000 0.000 0.000 {built-in method builtins.sum} > 100 1.977 0.020 1.977 0.020 {built-in method > pygame.display.flip} > 1 0.000 0.000 0.000 0.000 {method 'disable' of > '_lsprof.Profiler' objects} > 100 0.031 0.000 0.031 0.000 {method 'fill' of > 'pygame.Surface' objects} > 100 0.000 0.000 0.000 0.000 {method 'get_fps' of 'Clock' > objects} > 100 0.006 0.000 0.006 0.000 {method 'tick' of 'Clock' > objects} > This is: > Fedora 31 > Python 3.7.6 > Pygame 1.9.6 (I tried pygame 2.0.0.dev7 and it's the same) Takes beautifully the 20 milliseconds you'd expect for a 50 Hz display. Use pygame.display.update() if you want to take care of the framerate yourself. :) cheers! mar77i Sent with ProtonMail Secure Email.
[pygame] pygame.display.flip slow
Hi I'm experiencing very slow frame rates on a particular set up and need some help to understand what may be causing it. On this machine, the code below has an avg fram rate of around 45fps. The profiling output is: ncalls tottime percall cumtime percall filename:lineno(function) 10.0000.0002.0152.015 :1() 10.0010.0012.0152.015 fps_test.py:11(run) 10.0000.0002.0152.015 {built-in method builtins.exec} 10.0000.0000.0000.000 {built-in method builtins.print} 10.0000.0000.0000.000 {built-in method builtins.sum} 1001.9770.0201.9770.020 {built-in method pygame.display.flip} 10.0000.0000.0000.000 {method 'disable' of '_lsprof.Profiler' objects} 1000.0310.0000.0310.000 {method 'fill' of 'pygame.Surface' objects} 1000.0000.0000.0000.000 {method 'get_fps' of 'Clock' objects} 1000.0060.0000.0060.000 {method 'tick' of 'Clock' objects} This is: Fedora 31 Python 3.7.6 Pygame 1.9.6 (I tried pygame 2.0.0.dev7 and it's the same) The specs are fine: Intel(R) Core(TM) i7-5930K CPU @ 3.50GHz "glxgears" runs happily at 60fps on this machine. I can run the code below on a on slower machine (my laptop) with the same software config (F31/Python3.7/Pygame1.9.6) and easily get the 60fps. Any pointers to what may be causing this? Oh, a note, the larger the display size, the slower it gets. 1440x900 is just the size of the laptop screen, so the larger I could use to compare using the same version of Fedora. import pygame pygame.init() clock = pygame.time.Clock() screen_flags = 0 screen = pygame.display.set_mode((1440, 900), screen_flags) pygame.display.set_caption("FPS Test") print(pygame.display.Info()) def run(): x = 0 fps = [0] * 100 while x < 100: screen.fill(pygame.Color(0, 0, 0)) pygame.display.flip() clock.tick(60) fps[x] = clock.get_fps() x += 1 print(sum(fps)/100.) import cProfile cProfile.run('run()') Thanks.