Re: Debugging reason for python running unreasonably slow when adding numbers
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(100): > >>> s += i > >>> return s > >>> > >>> def sum2(): > >>> return sum(range(100)) > >> 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
Re: Debugging reason for python running unreasonably slow when adding numbers
On 3/20/2023 11:21 AM, Edmondo Giovannozzi wrote: def sum1(): s = 0 for i in range(100): s += i return s def sum2(): return sum(range(100)) 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
On 2023-03-20 15:21, Edmondo Giovannozzi wrote: > def sum1(): > s = 0 > for i in range(100): > s += i > return s > > def sum2(): > return sum(range(100)) 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
> > def sum1(): > > s = 0 > > for i in range(100): > > s += i > > return s > > > > def sum2(): > > return sum(range(100)) > 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
On 2023-03-15 17:09:52 +, 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(100): > s += i > return s > > def sum2(): > return sum(range(100)) 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. |_|_) || | | | h...@hjp.at |-- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" signature.asc Description: PGP signature -- https://mail.python.org/mailman/listinfo/python-list
Re: Debugging reason for python running unreasonably slow when adding numbers
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
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 Date: Wednesday, March 15, 2023 at 1:09 PM To: 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(100): s += i return s def sum2(): return sum(range(100)) 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 on behalf of David Raymond Date: Wednesday, March 15, 2023 at 11:46 AM To: 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
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(100): s += i return s def sum2(): return sum(range(100)) 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 on behalf of David Raymond Date: Wednesday, March 15, 2023 at 11:46 AM To: 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
> 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
On Thu, 16 Mar 2023 at 02:14, Thomas Passin wrote: > > On 3/15/2023 11:01 AM, Chris Angelico wrote: > > On Thu, 16 Mar 2023 at 01:26, David Raymond > > 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
On 3/15/2023 11:01 AM, Chris Angelico wrote: On Thu, 16 Mar 2023 at 01:26, David Raymond 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
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
On Thu, 16 Mar 2023 at 01:26, David Raymond 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
> 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
On Tue, 14 Mar 2023 at 16:27, 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 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
On Wed, 15 Mar 2023 at 08:53, Peter J. Holzer 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
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. |_|_) || | | | h...@hjp.at |-- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" signature.asc Description: PGP signature -- https://mail.python.org/mailman/listinfo/python-list
Re: Debugging reason for python running unreasonably slow when adding numbers
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
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() 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() 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 :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 :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