简体   繁体   中英

Is there any way to replace a for loop with something more efficient in python

My code below checks surrounding pixels to my object's pixel in python.

self.surr = [None, None, None, None, None, None, None, None]

for i in range(9):
#for x in range(-1, 2):
    #for y in range(-1, 2):
        if i != 5:
            x = i % 3 - 2
            y = int((i % 3) / 3) - 1

        if x == 0 and y == 0:
            pass
        else:
            PAI = allPixels[(self.x + x) % width][(self.y + y) % height] if allPixels[(self.x + x) % width][(self.y + y) % height] != None else None

        self.surr[(y * 3) + x] = (PAI)

return self.surr

This returns a list of length 8 that holds either a Pixel object or None . allPixels is a 2D array that also holds wither a Pixel object or None . I've tried then nested loops that are commented out but they run just a bit slower that the method I'm currently using. This however, is still too slow as if there are 3000 pixels on the screen, which is the lower bounds of the total pixels there will be on the screen in the end, do the maths and you have a LOT going on every frame.

How can I make this run faster using maybe NumPy or some other method?

If you want to see the whole code, it can be found here: https://pastebin.com/EuutUVjS

Thanks for any help you can give me!

What you're doing inherently requires looping—but if you can move that looping into numpy, it'll often get 5-20x faster.

In your case, what you're trying to do is to compare each pixel to its neighbors. How can you do that as an array-wide operation? Simple: compare the array to the same array shifted by 1.

Here's a simpler example:

>>> a = np.array([1,2,4,8,16])
>>> for i in range(1, len(a)):
...     print(a[i] - a[i-1], end=' ')
1 2 4 8
>>> print(a[1:] - a[:-1])
[1 2 4 8]

So, for a 2D array, it's just:

north = a[:-1]
ne = a[:-1,1:]
east = a[:,1:]
se = a[1:,1:]
south = a[1:]
sw = a[1:,:-1]
west = a[:,:-1]
nw = a[:-1,:-1]

Note that this isn't wasting a whole lot of time or memory building 8 extra arrays; it's just creating 8 views over the same memory.

See this answer on compsci for an example of using these shifted arrays for a Conway Game of Life simulation.

If you want to handle the borders differently, you may need to "zero-extend" the array, but that's the only complexity you're likely to run into.


However, there's a limit to how much benefit you can get out of numpy if you're storing Python objects in it. Normally, you want to store arrays of numbers.

I don't know what's in your Pixel objects, but let's pretend they're just color values, as three floats. In that case, you can use a 2D array with a structured dtype of three floats, or just a 3D array (row by column by rgb), either way using NaN values in place of None .

If you do that, array-wide operations can operate at near-machine-native speeds, including using SIMD operations for data-parallelism. If you don't, only the looping happens at native speeds; the arithmetic within the loop is still just as slow as in non-Numpy Python.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM