[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [pygame] is there a way to optimize this code?



My gut says this is most definitely the fastest way to go for small
numbers of snow flakes.
I suspect there is a certain point at which the numpy approach by Ian
wins out (especially if you can
optimize that a little more like Ian suggests, though I don't know
enough about numpy).

Some good tips to add to your bag of python optimization tricks:
- nested for-loops are bad news! move a loop into C whenever you can.
This can sometimes gain an order of magnitude
- numpy is fast, but you need to actually use its power. Just moving
the data into a numpy array and then operating on it in python won't
help
- local variables, avoiding attribute access, etc. are micro
optimizations. Use only as a last resort They'll rarely gain you more
than a few percent. It can make a difference in a tight loop, but
getting rid of the loop is usually much better.
- profile your code! This is the first thing to do, before you start
optimizing anything. I usually wrap the piece of code y I want to
profile in a function definition, and then run it with the cProfile
module, like so:

def x():
    <code to profile>
cProfile.runctx('x()', globals(), {'x' : x}, 'prof_stats')

you can look at the profile data in a python session:
>>> import pstats
>>> s = pstats.Stats('prof_stats')
>>> s.sort_stats('time').print_stats()

take a look at the cProfile and pstats modules in the standard
library, they've saved my butt on numerous occasions.

Hugo

On Mon, Aug 17, 2009 at 10:54 AM, <don@xxxxxxxxxxxxxxxxx> wrote:
>
> Hi
>
> Note that  didn't run any tests/profiling (no pygame installed on this machine).
> Anyway, here are my suggestions:
> 1) in "init()" instead of setting pixel per pixel to green use "pygame.draw.line()"
> 2) in "snowfall()" you check every pixel on every frame. this is most likly your bottleneck.
>   what I would do ist have a list with the positions of all snowflakes so you know exactly
>   where they are and don't have search the whole screen for them (especially if you only
>   have 8). This should greatly increase performance (instead of 640*480 iterations you only
>   need 8).
>
> After 2) you probably won't need the optimizations you implemented.
> Always remember "The Zen of Python". In this case: "Beautiful is better than ugly" and
> "Readability counts"!
>
>
> regards
> //Lorenz
>
>
>
> On Mon, 17 Aug 2009 02:33:30 -0400, Victor Noagbodji <noagbodjivictor@xxxxxxxxx> wrote:
>> hi, i'm following SDL tutorial here, http://sol.gfxile.net/gp/ch04.html
>>
>> this is the pygame equivalent. as you can see the code is not nice
>> looking. that's because i have tried all the optimization tricks i
>> know (local names, avoid dot operators, numpy array etc...) the result
>> is still awfully slow
>>
>> help.
>>
>> import numpy
>> import random
>> from sys import exit
>> from math import sin, cos
>>
>> import pygame
>> import pygame.event as event
>> import pygame.display as display
>>
>> from pygame.locals import *
>> from pygame import Surface
>> from pygame.time import get_ticks
>> from pygame.surfarray import pixels2d, blit_array, make_surface
>>
>> WIDTH = 640
>> HEIGHT = 480
>> RESOLUTION = (WIDTH, HEIGHT)
>>
>> def init(width, height, screen_array, green=int(0x007f00)):
>>   for i in xrange(width):
>>     sins = (sin((i + 3247) * 0.02) * 0.3 +
>>             sin((i + 2347) * 0.04) * 0.1 +
>>             sin((i + 4378) * 0.01) * 0.6)
>>     p = int(sins * 100 + 380)
>>     for j in range(p, height):
>>       screen_array[i, j] = green
>>
>> def newsnow(width, height, screen_array, white=int(0xffffff)):
>>   for i in xrange(8):
>>     screen_array[random.randint(1, 638), 0] = white
>>
>> def snowfall(width, height, screen_array, white=int(0xffffff), black=0):
>>   for j in xrange(height-2, -1, -1):
>>     for i in xrange(1, width-1):
>>       if screen_array[i, j] == white:
>>         if screen_array[i, j+1] == black:
>>           screen_array[i, j+1] = white
>>           screen_array[i, j] = black
>>
>> def main():
>>   pygame.init()
>>
>>   width = WIDTH
>>   height = HEIGHT
>>
>>   screen_surf = display.set_mode(RESOLUTION)
>>   screen_rect = screen_surf.get_rect()
>>   screen_array = pixels2d(screen_surf)
>>
>>   init(width, height, screen_array)
>>
>>   white = int(0xffffff)
>>   black = 0
>>
>>   display.update(screen_rect)
>>
>>   while True:
>>     tick = get_ticks()
>>
>>     newsnow(width, height, screen_array)
>>     #snowfall(width, height, screen_array)
>>
>>     for j in xrange(height-2, -1, -1):
>>       for i in xrange(1, width-1):
>>         if screen_array[i, j] == white:
>>           if screen_array[i, j+1] == black:
>>             screen_array[i, j+1] = white
>>             screen_array[i, j] = black
>>
>>     display.update(screen_rect)
>>
>>     for e in event.get():
>>       type = e.type
>>       if type == QUIT:
>>         exit()
>>       elif type == KEYUP and e.key == K_ESCAPE:
>>         return
>>
>> if __name__ == '__main__': main()
>>
>> --
>> paul victor noagbodji
>
>