Mailing List Archive

Debugging reason for python running unreasonably slow when adding numbers
I'm working on an NLP and I got bitten by an unreasonably slow behaviour in Python while operating with small amounts of numbers.

I have the following code:

```python
import random, time
from functools import reduce

def trainPerceptron(perceptron, data):
  learningRate = 0.002
  weights = perceptron['weights']
  error = 0
  for chunk in data:
      input = chunk['input']
      output = chunk['output']

      # 12x slower than equivalent JS
      sum_ = 0
      for key in input:
          v = weights[key]
          sum_ += v

      # 20x slower than equivalent JS
      #sum_ = reduce(lambda acc, key: acc + weights[key], input)

      actualOutput = sum_ if sum_ > 0 else 0

      expectedOutput = 1 if output == perceptron['id'] else 0
      currentError = expectedOutput - actualOutput
      if currentError:
          error += currentError ** 2
          change = currentError * learningRate
          for key in input:
              weights[key] += change

  return error

# Build mock data structure
data = [.{
   'input': random.sample(range(0, 5146), 10),
   'output': 0
} for _ in range(11514)]
perceptrons = [{
   'id': i,
   'weights': [0.0] * 5147,
} for i in range(60)] # simulate 60 perceptrons

# Simulate NLU
for i in range(151): # 150 iterations
  hrstart = time.perf_counter()
  for perceptron in perceptrons:
    trainPerceptron(perceptron, data)
  hrend = time.perf_counter()
  print(f'Epoch {i} - Time for training: {int((hrend - hrstart) * 1000)}ms')
```

Running it on my M1 MBP I get the following numbers.

```
Epoch 0 - Time for training: 199ms
Epoch 1 - Time for training: 198ms
Epoch 2 - Time for training: 199ms
Epoch 3 - Time for training: 197ms
Epoch 4 - Time for training: 199ms
...
Epoch 146 - Time for training: 198ms
Epoch 147 - Time for training: 200ms
Epoch 148 - Time for training: 198ms
Epoch 149 - Time for training: 198ms
Epoch 150 - Time for training: 198ms
```

Each epoch is taking around 200ms, which is unreasonably slow given the small amount of numbers that are being processed. I profiled the code with `cProfile` in order to find out what is going on:

```
         655306 function calls (655274 primitive calls) in 59.972 seconds

   Ordered by: cumulative time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
      3/1    0.000    0.000   59.972   59.972 {built-in method builtins.exec}
        1    0.005    0.005   59.972   59.972 poc-small.py:1(<module>)
     9060   59.850    0.007   59.850    0.007 poc-small.py:4(trainPerceptron)
        1    0.006    0.006    0.112    0.112 poc-small.py:34(<listcomp>)
    11514    0.039    0.000    0.106    0.000 random.py:382(sample)
   115232    0.034    0.000    0.047    0.000 random.py:235(_randbelow_with_getrandbits)
    11548    0.002    0.000    0.012    0.000 {built-in method builtins.isinstance}
    11514    0.002    0.000    0.010    0.000 <frozen abc>:117(__instancecheck__)
   183616    0.010    0.000    0.010    0.000 {method 'getrandbits' of '_random.Random' objects}
    11514    0.002    0.000    0.008    0.000 {built-in method _abc._abc_instancecheck}
    11514    0.002    0.000    0.006    0.000 <frozen abc>:121(__subclasscheck__)
   115140    0.005    0.000    0.005    0.000 {method 'add' of 'set' objects}
    11514    0.003    0.000    0.004    0.000 {built-in method _abc._abc_subclasscheck}
   115232    0.004    0.000    0.004    0.000 {method 'bit_length' of 'int' objects}
      151    0.003    0.000    0.003    0.000 {built-in method builtins.print}
```

This wasn't too helpful, so I tried with [line_profiler][1]:

```
Timer unit: 1e-06 s

Total time: 55.2079 s
File: poc-small.py
Function: trainPerceptron at line 4

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
     4                                           @profile
     5                                           def trainPerceptron(perceptron, data):
     6      1214        301.0      0.2      0.0    learningRate = 0.002
     7      1214        255.0      0.2      0.0    weights = perceptron['weights']
     8      1214        114.0      0.1      0.0    error = 0
     9  13973840    1742427.0      0.1      3.2    for chunk in data:
    10  13973840    1655043.0      0.1      3.0        input = chunk['input']
    11  13973840    1487543.0      0.1      2.7        output = chunk['output']
    12
    13                                                 # 12x slower than equivalent JS
    14  13973840    1210755.0      0.1      2.2        sum_ = 0
    15 139738397   13821056.0      0.1     25.0        for key in input:
    16 139738397   13794656.0      0.1     25.0            v = weights[key]
    17 139738396   14942692.0      0.1     27.1            sum_ += v
    18
    19                                                 # 20x slower than equivalent JS
    20                                                 #sum_ = reduce(lambda acc, key: acc + weights[key], input)
    21
    22  13973839    1618273.0      0.1      2.9        actualOutput = sum_ if sum_ > 0 else 0
    23
    24  13973839    1689194.0      0.1      3.1        expectedOutput = 1 if output == perceptron['id'] else 0
    25  13973839    1365346.0      0.1      2.5        currentError = expectedOutput - actualOutput
    26  13732045    1211916.0      0.1      2.2        if currentError:
    27    241794      38375.0      0.2      0.1            error += currentError ** 2
    28    241794      25377.0      0.1      0.0            change = currentError * learningRate
    29   2417940     271237.0      0.1      0.5            for key in input:
    30   2417940     332890.0      0.1      0.6                weights[key] += change
    31
    32      1213        405.0      0.3      0.0    return error
```

This shows that these 3 lines (that are adding the numbers) are taking the entire runtime budget:

```python
for key in input:
   v = weights[key]
   sum_ += v
```

I thought throwing numpy at the problem in order to speed it up, but `input` has a very small size, which means that the overhead of calling numpy will hurt the performance more than the gains obtained by making the math operations with it.

Anyhow, adding numbers shouldn't be that slow, which makes me believe something weird is going on with Python. In order to confirm my theory, I ported the code to Javascript. This is the result:

```js
function trainPerceptron(perceptron, data) {
  const learningRate = 0.002;
  const weights = perceptron['weights'];
  let error = 0;
  for (const chunk of data) {
    const input = chunk['input'];
    const output = chunk['output'];

    const sum = input.reduce((acc, key) => acc + weights[key], 0);
    const actualOutput = sum > 0 ? sum : 0;

    const expectedOutput = output === perceptron['id'] ? 1 : 0;
    const currentError = expectedOutput - actualOutput;
    if (currentError) {
      error += currentError ** 2;
      const change = currentError * learningRate;
      for (const key in input) {
        weights[key] += change;
      }
    }
  }
  return error;
}

// Build mock data structure
const data = new Array(11514);
for (let i = 0; i < data.length; i++) {
  const inputSet = new Set();
  while (inputSet.size < 10) {
    inputSet.add(Math.floor(Math.random() * 5146));
  }
  const input = Array.from(inputSet);
  data[i] = { input: input, output: 0 };
}

const perceptrons = Array.from({ length: 60 }, (_, i) => ({
  id: i,
  weights: Array.from({ length: 5147 }, () => 0.0),
})); // simulate 60 perceptrons

// Simulate NLU
for (let i = 0; i < 151; i++) { // 150 iterations
  const hrstart = performance.now();
  for (const perceptron of perceptrons) {
    trainPerceptron(perceptron, data);
  }
  const hrend = performance.now();
  console.log(`Epoch ${i} - Time for training: ${Math.floor(hrend - hrstart)}ms`);
}
```

When I run the JS code I get the following numbers:

```
Epoch 0 - Time for training: 30ms
Epoch 1 - Time for training: 18ms
Epoch 2 - Time for training: 17ms
Epoch 3 - Time for training: 17ms
Epoch 4 - Time for training: 17ms
...
Epoch 147 - Time for training: 17ms
Epoch 148 - Time for training: 17ms
Epoch 149 - Time for training: 17ms
Epoch 150 - Time for training: 17ms
```

These numbers confirm my theory. Python is being unreasonably slow. Any idea why or what exactly is making it perform so poorly?

Runtime details:

MacOS Ventura 13.2.1 (22D68)
Macbook Pro M1 Pro 32GB
Python 3.11.0 (native Apple Silicon)

Regards!

  [1]: https://github.com/pyutils/line_profiler
--
https://mail.python.org/mailman/listinfo/python-list
Re: Debugging reason for python running unreasonably slow when adding numbers [ In reply to ]
On 3/14/2023 3:48 AM, Alexander Nestorov wrote:
> I'm working on an NLP and I got bitten by an unreasonably slow behaviour in Python while operating with small amounts of numbers.
>
> I have the following code:
>
> ```python
> import random, time
> from functools import reduce
>
> def trainPerceptron(perceptron, data):
>   learningRate = 0.002
>   weights = perceptron['weights']
>   error = 0
>   for chunk in data:
>       input = chunk['input']
>       output = chunk['output']
>
>       # 12x slower than equivalent JS
>       sum_ = 0
>       for key in input:
>           v = weights[key]
>           sum_ += v
>
>       # 20x slower than equivalent JS
>       #sum_ = reduce(lambda acc, key: acc + weights[key], input)
>
>       actualOutput = sum_ if sum_ > 0 else 0
>
>       expectedOutput = 1 if output == perceptron['id'] else 0
>       currentError = expectedOutput - actualOutput
>       if currentError:
>           error += currentError ** 2
>           change = currentError * learningRate
>           for key in input:
>               weights[key] += change

[snip]
Just a speculation, but the difference with the javascript behavior
might be because the JS JIT compiler kicked in for these loops.

--
https://mail.python.org/mailman/listinfo/python-list
Re: Debugging reason for python running unreasonably slow when adding numbers [ In reply to ]
On 2023-03-14 16:48:24 +0900, Alexander Nestorov wrote:
> I'm working on an NLP and I got bitten by an unreasonably slow
> behaviour in Python while operating with small amounts of numbers.
>
> I have the following code:
[...]
> ?? ? ?# 12x slower than equivalent JS
> ?? ? ?sum_ = 0
> ?? ? ?for key in input:
> ?? ? ? ? ?v = weights[key]
> ?? ? ? ? ?sum_ += v
>
> ?? ? ?# 20x slower than equivalent JS
> ?? ? ?#sum_ = reduce(lambda acc, key: acc + weights[key], input)

Not surprising. Modern JavaScript implementations have a JIT compiler.
CPython doesn't.

You may want to try PyPy if your code uses tight loops like that.

Or alternatively it may be possible to use numpy to do these operations.

hp

--
_ | Peter J. Holzer | Story must make more sense than reality.
|_|_) | |
| | | hjp@hjp.at | -- Charles Stross, "Creative writing
__/ | http://www.hjp.at/ | challenge!"
Re: Debugging reason for python running unreasonably slow when adding numbers [ In reply to ]
On Wed, 15 Mar 2023 at 08:53, Peter J. Holzer <hjp-python@hjp.at> wrote:
>
> On 2023-03-14 16:48:24 +0900, Alexander Nestorov wrote:
> > I'm working on an NLP and I got bitten by an unreasonably slow
> > behaviour in Python while operating with small amounts of numbers.
> >
> > I have the following code:
> [...]
> > # 12x slower than equivalent JS
> > sum_ = 0
> > for key in input:
> > v = weights[key]
> > sum_ += v
> >
> > # 20x slower than equivalent JS
> > #sum_ = reduce(lambda acc, key: acc + weights[key], input)
>
> Not surprising. Modern JavaScript implementations have a JIT compiler.
> CPython doesn't.
>
> You may want to try PyPy if your code uses tight loops like that.
>
> Or alternatively it may be possible to use numpy to do these operations.
>

Or use the sum() builtin rather than reduce(), which was
*deliberately* removed from the builtins. The fact that you can get
sum() without importing, but have to go and reach for functools to get
reduce(), is a hint that you probably shouldn't use reduce when sum
will work.

Naive code is almost always going to be slower than smart code, and
comparing "equivalent" code across languages is almost always an
unfair comparison to one of them.

ChrisA
--
https://mail.python.org/mailman/listinfo/python-list
Re: Debugging reason for python running unreasonably slow when adding numbers [ In reply to ]
On Tue, 14 Mar 2023 at 16:27, Alexander Nestorov <alexandernst@gmail.com> wrote:
>
> I'm working on an NLP and I got bitten by an unreasonably slow behaviour in Python while operating with small amounts of numbers.
>
> I have the following code:
>
> ```python
> import random, time
> from functools import reduce
>
> def trainPerceptron(perceptron, data):
> learningRate = 0.002
> weights = perceptron['weights']
> error = 0
> for chunk in data:
> input = chunk['input']
> output = chunk['output']
>
> # 12x slower than equivalent JS
> sum_ = 0
> for key in input:
> v = weights[key]
> sum_ += v

In Python something like your task here would usually use something
along the lines of NumPy. Your two innermost loops involve adding up a
subset of numbers from a list chosen using a list of indices. This is
something that numpy can do much more efficiently with its fancy
indexing e.g.:

In [3]: a = np.array([1, 2, 3, 4, 5, 6, 7])

In [4]: b = np.array([0, 3, 5])

In [5]: a[b]
Out[5]: array([1, 4, 6])

In [6]: a[b].sum()
Out[6]: 11

This a[b].sum() operation in your code would be weights[input].sum()
and would be much faster than the loop shown (the speed difference
will be larger if you increase the size of the input array).

--
Oscar
--
https://mail.python.org/mailman/listinfo/python-list
RE: Debugging reason for python running unreasonably slow when adding numbers [ In reply to ]
> Or use the sum() builtin rather than reduce(), which was
> *deliberately* removed from the builtins. The fact that you can get
> sum() without importing, but have to go and reach for functools to get
> reduce(), is a hint that you probably shouldn't use reduce when sum
> will work.

Out of curiosity I tried a couple variations and am a little confused by the results. Maybe I'm having a brain fart and am missing something obvious?

Each of these was run with the same "data" and "perceptrons" values to keep that fair.
Times are averages over 150 iterations like the original.
The only thing changed in the trainPerceptron function was how to calculate sum_


Original:
sum_ = 0
for key in input:
v = weights[key]
sum_ += v
418ms

The reduce version:
sum_ = reduce(lambda acc, key: acc + weights[key], input)
758ms

Getting rid of the assignment to v in the original version:
sum_ = 0
for key in input:
sum_ += weights[key]
380ms

But then using sum seems to be slower

sum with generator expression:
sum_ = sum(weights[key] for key in input)
638ms

sum with list comprehension:
sum_ = sum([weights[key] for key in input])
496ms

math.fsum with generator expression:
sum_ = math.fsum(weights[key] for key in input)
618ms

math.fsum with list comprehension:
sum_ = math.fsum([weights[key] for key in input])
480ms


I'm not quite sure why the built-in sum functions are slower than the for loop,
or why they're slower with the generator expression than with the list comprehension.
--
https://mail.python.org/mailman/listinfo/python-list
Re: Debugging reason for python running unreasonably slow when adding numbers [ In reply to ]
On 3/15/2023 10:24 AM, David Raymond wrote:
>> Or use the sum() builtin rather than reduce(), which was
>> *deliberately* removed from the builtins. The fact that you can get
>> sum() without importing, but have to go and reach for functools to get
>> reduce(), is a hint that you probably shouldn't use reduce when sum
>> will work.
>
> Out of curiosity I tried a couple variations and am a little confused by the results. Maybe I'm having a brain fart and am missing something obvious?
>
> Each of these was run with the same "data" and "perceptrons" values to keep that fair.
> Times are averages over 150 iterations like the original.
> The only thing changed in the trainPerceptron function was how to calculate sum_
>
>
> Original:
> sum_ = 0
> for key in input:
> v = weights[key]
> sum_ += v
> 418ms
>
> The reduce version:
> sum_ = reduce(lambda acc, key: acc + weights[key], input)
> 758ms
>
> Getting rid of the assignment to v in the original version:
> sum_ = 0
> for key in input:
> sum_ += weights[key]
> 380ms
>
> But then using sum seems to be slower
>
> sum with generator expression:
> sum_ = sum(weights[key] for key in input)
> 638ms
>
> sum with list comprehension:
> sum_ = sum([weights[key] for key in input])
> 496ms
>
> math.fsum with generator expression:
> sum_ = math.fsum(weights[key] for key in input)
> 618ms
>
> math.fsum with list comprehension:
> sum_ = math.fsum([weights[key] for key in input])
> 480ms
>
>
> I'm not quite sure why the built-in sum functions are slower than the for loop,
> or why they're slower with the generator expression than with the list comprehension.

I tried similar variations yesterday and got similar results. All the
sum() versions I tried were slower. Like you, I got the smallest times for

> for key in input:
> sum_ += weights[key]

but I didn't get as much of a difference as you did.

I surmise that in using the sum() variations, that the entire sequence
was constructed first, and then iterated over. In the non-sum()
versions, no new sequence had to be constructed first, so it would make
sense for the latter to be slower.
--
https://mail.python.org/mailman/listinfo/python-list
Re: Debugging reason for python running unreasonably slow when adding numbers [ In reply to ]
On Thu, 16 Mar 2023 at 01:26, David Raymond <David.Raymond@tomtom.com> wrote:
> I'm not quite sure why the built-in sum functions are slower than the for loop,
> or why they're slower with the generator expression than with the list comprehension.

For small-to-medium data sizes, genexps are slower than list comps,
but use less memory. (At some point, using less memory translates
directly into faster runtime.) But even the sum-with-genexp version is
notably faster than reduce.

Is 'weights' a dictionary? You're iterating over it, then subscripting
every time. If it is, try simply taking the sum of weights.values(),
as this should be significantly faster.

ChrisA
--
https://mail.python.org/mailman/listinfo/python-list
Re: Debugging reason for python running unreasonably slow when adding numbers [ In reply to ]
On 3/15/2023 11:01 AM, Chris Angelico wrote:
> On Thu, 16 Mar 2023 at 01:26, David Raymond <David.Raymond@tomtom.com> wrote:
>> I'm not quite sure why the built-in sum functions are slower than the for loop,
>> or why they're slower with the generator expression than with the list comprehension.
>
> For small-to-medium data sizes, genexps are slower than list comps,
> but use less memory. (At some point, using less memory translates
> directly into faster runtime.) But even the sum-with-genexp version is
> notably faster than reduce.
>
> Is 'weights' a dictionary? You're iterating over it, then subscripting
> every time. If it is, try simply taking the sum of weights.values(),
> as this should be significantly faster.

It's a list.

--
https://mail.python.org/mailman/listinfo/python-list
Re: Debugging reason for python running unreasonably slow when adding numbers [ In reply to ]
On Thu, 16 Mar 2023 at 02:14, Thomas Passin <list1@tompassin.net> wrote:
>
> On 3/15/2023 11:01 AM, Chris Angelico wrote:
> > On Thu, 16 Mar 2023 at 01:26, David Raymond <David.Raymond@tomtom.com> wrote:
> >> I'm not quite sure why the built-in sum functions are slower than the for loop,
> >> or why they're slower with the generator expression than with the list comprehension.
> >
> > For small-to-medium data sizes, genexps are slower than list comps,
> > but use less memory. (At some point, using less memory translates
> > directly into faster runtime.) But even the sum-with-genexp version is
> > notably faster than reduce.
> >
> > Is 'weights' a dictionary? You're iterating over it, then subscripting
> > every time. If it is, try simply taking the sum of weights.values(),
> > as this should be significantly faster.
>
> It's a list.
>

Then I'm very confused as to how things are being done, so I will shut
up. There's not enough information here to give performance advice
without actually being a subject-matter expert already.

ChrisA
--
https://mail.python.org/mailman/listinfo/python-list
RE: Debugging reason for python running unreasonably slow when adding numbers [ In reply to ]
> Then I'm very confused as to how things are being done, so I will shut
> up. There's not enough information here to give performance advice
> without actually being a subject-matter expert already.

Short version: In this specific case "weights" is a 5,147 element list of floats, and "input" is a 10 element list of integers which has the indexes of the 10 elements in weights that he wants to add up.

sum_ = 0
for key in input:
sum_ += weights[key]

vs

sum_ = sum(weights[key] for key in input)

vs... other ways
--
https://mail.python.org/mailman/listinfo/python-list
Re: Debugging reason for python running unreasonably slow when adding numbers [ In reply to ]
Sum is faster than iteration in the general case.

Lifting a test program from Stack Overflow https://stackoverflow.com/questions/24578896/python-built-in-sum-function-vs-for-loop-performance,

import timeit

def sum1():
s = 0
for i in range(1000000):
s += i
return s

def sum2():
return sum(range(1000000))

print('For Loop Sum:', timeit.timeit(sum1, number=100))
print( 'Built-in Sum:', timeit.timeit(sum2, number=100))

---

For Loop Sum: 7.726335353218019
Built-in Sum: 1.0398506000638008

---

From: Python-list <python-list-bounces+gweatherby=uchc.edu@python.org> on behalf of David Raymond <David.Raymond@tomtom.com>
Date: Wednesday, March 15, 2023 at 11:46 AM
To: python-list@python.org <python-list@python.org>
Subject: RE: Debugging reason for python running unreasonably slow when adding numbers
*** Attention: This is an external email. Use caution responding, opening attachments or clicking on links. ***

> Then I'm very confused as to how things are being done, so I will shut
> up. There's not enough information here to give performance advice
> without actually being a subject-matter expert already.

Short version: In this specific case "weights" is a 5,147 element list of floats, and "input" is a 10 element list of integers which has the indexes of the 10 elements in weights that he wants to add up.

sum_ = 0
for key in input:
sum_ += weights[key]

vs

sum_ = sum(weights[key] for key in input)

vs... other ways
--
https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!ikhJJxqJnllDHh6JKaMX8g2K-Ceq6ZiRDJxX7AbS-1AiBIrdAmA2qjBtYZbxel2mktyno1s9iJGo_zAl5alBIWxoVXE$<https://urldefense.com/v3/__https:/mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!ikhJJxqJnllDHh6JKaMX8g2K-Ceq6ZiRDJxX7AbS-1AiBIrdAmA2qjBtYZbxel2mktyno1s9iJGo_zAl5alBIWxoVXE$>
--
https://mail.python.org/mailman/listinfo/python-list
Re: Debugging reason for python running unreasonably slow when adding numbers [ In reply to ]
Moving the generator out:

import timeit

thedata = [i for i in range(1_000_000)]
def sum1():
s = 0
for i in thedata:
s += i
return s

def sum2():
return sum(thedata)

print('For Loop Sum:', timeit.timeit(sum1, number=100))
print( 'Built-in Sum:', timeit.timeit(sum2, number=100))

---
For Loop Sum: 6.984986504539847
Built-in Sum: 0.5175364706665277

From: Weatherby,Gerard <gweatherby@uchc.edu>
Date: Wednesday, March 15, 2023 at 1:09 PM
To: python-list@python.org <python-list@python.org>
Subject: Re: Debugging reason for python running unreasonably slow when adding numbers
Sum is faster than iteration in the general case.

Lifting a test program from Stack Overflow https://stackoverflow.com/questions/24578896/python-built-in-sum-function-vs-for-loop-performance,


import timeit

def sum1():
s = 0
for i in range(1000000):
s += i
return s

def sum2():
return sum(range(1000000))

print('For Loop Sum:', timeit.timeit(sum1, number=100))
print( 'Built-in Sum:', timeit.timeit(sum2, number=100))

---

For Loop Sum: 7.726335353218019
Built-in Sum: 1.0398506000638008

---


From: Python-list <python-list-bounces+gweatherby=uchc.edu@python.org> on behalf of David Raymond <David.Raymond@tomtom.com>
Date: Wednesday, March 15, 2023 at 11:46 AM
To: python-list@python.org <python-list@python.org>
Subject: RE: Debugging reason for python running unreasonably slow when adding numbers
*** Attention: This is an external email. Use caution responding, opening attachments or clicking on links. ***

> Then I'm very confused as to how things are being done, so I will shut
> up. There's not enough information here to give performance advice
> without actually being a subject-matter expert already.

Short version: In this specific case "weights" is a 5,147 element list of floats, and "input" is a 10 element list of integers which has the indexes of the 10 elements in weights that he wants to add up.

sum_ = 0
for key in input:
sum_ += weights[key]

vs

sum_ = sum(weights[key] for key in input)

vs... other ways
--
https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!ikhJJxqJnllDHh6JKaMX8g2K-Ceq6ZiRDJxX7AbS-1AiBIrdAmA2qjBtYZbxel2mktyno1s9iJGo_zAl5alBIWxoVXE$<https://urldefense.com/v3/__https:/mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!ikhJJxqJnllDHh6JKaMX8g2K-Ceq6ZiRDJxX7AbS-1AiBIrdAmA2qjBtYZbxel2mktyno1s9iJGo_zAl5alBIWxoVXE$>
--
https://mail.python.org/mailman/listinfo/python-list
Re: Debugging reason for python running unreasonably slow when adding numbers [ In reply to ]
Op 14/03/2023 om 8:48 schreef Alexander Nestorov:
> I have the following code:
>
> ...
> for i in range(151): # 150 iterations
>    ...
Nothing to do with your actual question and it's probably just a small
oversight, but still I thought it was worth a mention: that comment does
not accurately describe the code; the code is actually doing 151
iterations, numbered 0 up to and including 150.

--
"I've come up with a set of rules that describe our reactions to technologies:
1. Anything that is in the world when you’re born is normal and ordinary and is
just a natural part of the way the world works.
2. Anything that's invented between when you’re fifteen and thirty-five is new
and exciting and revolutionary and you can probably get a career in it.
3. Anything invented after you're thirty-five is against the natural order of things."
-- Douglas Adams, The Salmon of Doubt

--
https://mail.python.org/mailman/listinfo/python-list
Re: Debugging reason for python running unreasonably slow when adding numbers [ In reply to ]
On 2023-03-15 17:09:52 +0000, Weatherby,Gerard wrote:
> Sum is faster than iteration in the general case.

I'd say this is the special case, not the general case.

> def sum1():
> s = 0
> for i in range(1000000):
> s += i
> return s
>
> def sum2():
> return sum(range(1000000))

Here you already have the numbers you want to add.

The OP needed to compute those numbers first.

hp

--
_ | Peter J. Holzer | Story must make more sense than reality.
|_|_) | |
| | | hjp@hjp.at | -- Charles Stross, "Creative writing
__/ | http://www.hjp.at/ | challenge!"
Re: Debugging reason for python running unreasonably slow when adding numbers [ In reply to ]
> > def sum1():
> > s = 0
> > for i in range(1000000):
> > s += i
> > return s
> >
> > def sum2():
> > return sum(range(1000000))
> Here you already have the numbers you want to add.

Actually using numpy you'll be much faster in this case:

§ import numpy as np
§ def sum3():
§ return np.arange(1_000_000, dtype=np.int64).sum()

On my computer sum1 takes 44 ms, while the numpy version just 2.6 ms
One problem is that sum2 gives the wrong result. This is why I used np.arange with dtype=np.int64.

sum2 evidently doesn't uses the python "big integers" e restrict the result to 32 bits.

--
https://mail.python.org/mailman/listinfo/python-list
Re: Debugging reason for python running unreasonably slow when adding numbers [ In reply to ]
On 2023-03-20 15:21, Edmondo Giovannozzi wrote:
>
>> > def sum1():
>> > s = 0
>> > for i in range(1000000):
>> > s += i
>> > return s
>> >
>> > def sum2():
>> > return sum(range(1000000))
>> Here you already have the numbers you want to add.
>
> Actually using numpy you'll be much faster in this case:
>
> § import numpy as np
> § def sum3():
> § return np.arange(1_000_000, dtype=np.int64).sum()
>
> On my computer sum1 takes 44 ms, while the numpy version just 2.6 ms
> One problem is that sum2 gives the wrong result. This is why I used np.arange with dtype=np.int64.
>
> sum2 evidently doesn't uses the python "big integers" e restrict the result to 32 bits.
>
On my computer they all give the same result, as I'd expect.
--
https://mail.python.org/mailman/listinfo/python-list
Re: Debugging reason for python running unreasonably slow when adding numbers [ In reply to ]
On 3/20/2023 11:21 AM, Edmondo Giovannozzi wrote:
>
>>> def sum1():
>>> s = 0
>>> for i in range(1000000):
>>> s += i
>>> return s
>>>
>>> def sum2():
>>> return sum(range(1000000))
>> Here you already have the numbers you want to add.
>
> Actually using numpy you'll be much faster in this case:
>
> § import numpy as np
> § def sum3():
> § return np.arange(1_000_000, dtype=np.int64).sum()
>
> On my computer sum1 takes 44 ms, while the numpy version just 2.6 ms
> One problem is that sum2 gives the wrong result. This is why I used np.arange with dtype=np.int64.

On my computer they all give the same result.

Python 3.10.9, PyQt version 6.4.1
Windows 10 AMD64 (build 10.0.19044) SP0
Processor: 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz, 1690 Mhz, 4
Core(s), 8 Logical Processor(s)


> sum2 evidently doesn't uses the python "big integers" e restrict the result to 32 bits.

What about your system? Let's see if we can figure the reason for the
difference.

--
https://mail.python.org/mailman/listinfo/python-list
Re: Debugging reason for python running unreasonably slow when adding numbers [ In reply to ]
Il giorno lunedì 20 marzo 2023 alle 19:10:26 UTC+1 Thomas Passin ha scritto:
> On 3/20/2023 11:21 AM, Edmondo Giovannozzi wrote:
> >
> >>> def sum1():
> >>> s = 0
> >>> for i in range(1000000):
> >>> s += i
> >>> return s
> >>>
> >>> def sum2():
> >>> return sum(range(1000000))
> >> Here you already have the numbers you want to add.
> >
> > Actually using numpy you'll be much faster in this case:
> >
> > § import numpy as np
> > § def sum3():
> > § return np.arange(1_000_000, dtype=np.int64).sum()
> >
> > On my computer sum1 takes 44 ms, while the numpy version just 2.6 ms
> > One problem is that sum2 gives the wrong result. This is why I used np.arange with dtype=np.int64.
> On my computer they all give the same result.
>
> Python 3.10.9, PyQt version 6.4.1
> Windows 10 AMD64 (build 10.0.19044) SP0
> Processor: 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz, 1690 Mhz, 4
> Core(s), 8 Logical Processor(s)
> > sum2 evidently doesn't uses the python "big integers" e restrict the result to 32 bits.
> What about your system? Let's see if we can figure the reason for the
> difference.

I'm using winpython on Windows 11 and the python version is, well, 3.11:

But it is my fault, sorry, I realised now that ipython is importing numpy namespace and the numpy sum function is overwriting the intrinsic sum.
The intrinsic sum is behaving correctly and is faster when used in sum(range(1_000_000)) then the numpy version.


--
https://mail.python.org/mailman/listinfo/python-list