0

Just figured out that 2 nested loops work extremely slow in Python. CPU load stays around 0% but it still works slow. Why? How can I fix that?

Initialization (shouldn't comment it to make it work fast):

    a = imresize(image, (maxY, maxX), 'lanczos')
    b = imresize(image, (maxY * 2, maxX), 'lanczos')

Slow code:

    result = np.empty((maxY, maxX, 3), dtype=np.uint16)
    for y in range(maxY):
        for x in range(maxX):
            result[y, x] = [a[y, x], a[y, x], a[y, x]]

And this one works even more slow:

    result = np.empty((maxY, maxX, 3), dtype=np.uint16)
    for y in range(maxY):
        for x in range(maxX):
            result[y, x] = [a[y, x], b[y*2, x], b[y*2+1, x]]

Is there any other more effective code to achieve the same results?

Shape of a is (299, 299), b - (598, 299), result - (299, 299, 3). I call the code about 5000 times (and wait about 10 minutes for that amount of data).

If I comment the provided code everything works just a second.

19
  • 1
    1) fix your algorithm, 2) use numpy 3) use CPython are all options. Without more info, it's hard to say anything Commented Sep 21, 2017 at 0:20
  • 1
    No info about any of those variables or your cpu-load evaluation is given... Commented Sep 21, 2017 at 0:21
  • 1
    Always, always, always use NumPy when your doing operations on every element of an array. Commented Sep 21, 2017 at 0:22
  • 1
    Show a more complete code (definition and shapes of all those vars) and tell us how you measured cpu-load. Commented Sep 21, 2017 at 0:23
  • 1
    You said you have arrays of uint8, but did not use numpy already. That does not make much sense (in most cases). Commented Sep 21, 2017 at 0:25

2 Answers 2

2

Allocating memory is always slow in every language, so you need to avoid it. In your example, you create a list in every loop.

You should use something like the following:

result = np.empty((maxY, maxX, 3), dtype=np.uint16)
for y in range(maxY):
    for x in range(maxX):
        result[y, x, 0] = a[y, x]
        result[y, x, 1] = a[y, x]
        result[y, x, 2] = a[y, x]

Or as mentioned by @user3237718, you should use:

result = np.empty((maxY, maxX, 3), dtype=np.uint16)
for i in range(3):
    result[:, :, i] = a

The key point is to avoid dynamically allocating memory.

Sign up to request clarification or add additional context in comments.

2 Comments

Already tried the first version of the code myself. It helped only a little.
@Dmitry Try the second one, it helps a lot.
1

please use vectorization to fix your code. like that:

result[:,:,0] = a

1 Comment

Nice idea! But I still have to use one loop with it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.