Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #83184 > unrolled thread
| Started by | austin aigbe <eshikafe@gmail.com> |
|---|---|
| First post | 2015-01-03 15:19 -0800 |
| Last post | 2015-01-04 13:24 +0100 |
| Articles | 9 — 6 participants |
Back to article view | Back to comp.lang.python
list comparison vs integer comparison, which is more efficient? austin aigbe <eshikafe@gmail.com> - 2015-01-03 15:19 -0800
Re: list comparison vs integer comparison, which is more efficient? Chris Angelico <rosuav@gmail.com> - 2015-01-04 10:40 +1100
Re: list comparison vs integer comparison, which is more efficient? Terry Reedy <tjreedy@udel.edu> - 2015-01-04 02:10 -0500
Re: list comparison vs integer comparison, which is more efficient? austin aigbe <eshikafe@gmail.com> - 2015-01-04 03:20 -0800
Re: list comparison vs integer comparison, which is more efficient? austin aigbe <eshikafe@gmail.com> - 2015-01-04 04:17 -0800
Re: list comparison vs integer comparison, which is more efficient? Christian Gollwitzer <auriocus@gmx.de> - 2015-01-04 13:22 +0100
Re: list comparison vs integer comparison, which is more efficient? Mark Lawrence <breamoreboy@yahoo.co.uk> - 2015-01-04 12:30 +0000
Re: list comparison vs integer comparison, which is more efficient? Chris Angelico <rosuav@gmail.com> - 2015-01-04 23:25 +1100
Re: list comparison vs integer comparison, which is more efficient? Jonas Wielicki <jonas@wielicki.name> - 2015-01-04 13:24 +0100
| From | austin aigbe <eshikafe@gmail.com> |
|---|---|
| Date | 2015-01-03 15:19 -0800 |
| Subject | list comparison vs integer comparison, which is more efficient? |
| Message-ID | <d27586b9-017a-4519-a6bb-e0a1fac005d0@googlegroups.com> |
Hi,
I am currently implementing the LTE physical layer in Python (ver 2.7.7).
For the qpsk, 16qam and 64qam modulation I would like to know which is more efficient to use, between an integer comparison and a list comparison:
Integer comparison: bit_pair as an integer value before comparison
# QPSK - TS 36.211 V12.2.0, section 7.1.2, Table 7.1.2-1
def mp_qpsk(self):
r = []
for i in range(self.nbits/2):
bit_pair = (self.sbits[i*2] << 1) | self.sbits[i*2+1]
if bit_pair == 0:
r.append(complex(1/math.sqrt(2),1/math.sqrt(2)))
elif bit_pair == 1:
r.append(complex(1/math.sqrt(2),-1/math.sqrt(2)))
elif bit_pair == 2:
r.append(complex(-1/math.sqrt(2),1/math.sqrt(2)))
elif bit_pair == 3:
r.append(complex(-1/math.sqrt(2),-1/math.sqrt(2)))
return r
List comparison: bit_pair as a list before comparison
# QPSK - TS 36.211 V12.2.0, section 7.1.2, Table 7.1.2-1
def mp_qpsk(self):
r = []
for i in range(self.nbits/2):
bit_pair = self.sbits[i*2:i*2+2]
if bit_pair == [0,0]:
r.append(complex(1/math.sqrt(2),1/math.sqrt(2)))
elif bit_pair == [0,1]:
r.append(complex(1/math.sqrt(2),-1/math.sqrt(2)))
elif bit_pair == [1,0]:
r.append(complex(-1/math.sqrt(2),1/math.sqrt(2)))
elif bit_pair == [1,1]:
r.append(complex(-1/math.sqrt(2),-1/math.sqrt(2)))
return r
Thanks
[toc] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2015-01-04 10:40 +1100 |
| Message-ID | <mailman.17363.1420328417.18130.python-list@python.org> |
| In reply to | #83184 |
On Sun, Jan 4, 2015 at 10:19 AM, austin aigbe <eshikafe@gmail.com> wrote:
> I would like to know which is more efficient to use, between an integer comparison and a list comparison:
You can test them with the timeit module, but my personal suspicion is
that any difference between them will be utterly and completely
dwarfed by all your sqrt(2) calls in the complex constructors. If you
break those out, and use a tuple instead of a list, you could write
this very simply and tidily:
bits = {
(0,0): complex(1/math.sqrt(2),1/math.sqrt(2)),
(0,1): complex(1/math.sqrt(2),-1/math.sqrt(2)),
(1,0): complex(-1/math.sqrt(2),1/math.sqrt(2)),
(1,1): complex(-1/math.sqrt(2),-1/math.sqrt(2)),
}
# QPSK - TS 36.211 V12.2.0, section 7.1.2, Table 7.1.2-1
def mp_qpsk(self):
r = []
for i in range(self.nbits/2):
bit_pair = self.sbits[i*2:i*2+2]
r.append(bits[tuple(bit_pair)])
return r
At this point, your loop looks very much like a list comprehension in
full form, so you can make a simple conversion:
# From itertools recipes
# https://docs.python.org/3/library/itertools.html
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = tee(iterable)
next(b, None)
return zip(a, b)
# Replace zip() with izip() for the Python 2 equivalent.
def mp_qpsk(self):
return [bits[pair] for pair in pairwise(self.sbits)]
How's that look? I don't care if it's faster or not, I prefer this form :)
ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Terry Reedy <tjreedy@udel.edu> |
|---|---|
| Date | 2015-01-04 02:10 -0500 |
| Message-ID | <mailman.17365.1420355468.18130.python-list@python.org> |
| In reply to | #83184 |
On 1/3/2015 6:19 PM, austin aigbe wrote:
> I am currently implementing the LTE physical layer in Python (ver 2.7.7).
> For the qpsk, 16qam and 64qam modulation I would like to know which is more efficient to use, between an integer comparison and a list comparison:
>
> Integer comparison: bit_pair as an integer value before comparison
>
> # QPSK - TS 36.211 V12.2.0, section 7.1.2, Table 7.1.2-1
> def mp_qpsk(self):
> r = []
> for i in range(self.nbits/2):
> bit_pair = (self.sbits[i*2] << 1) | self.sbits[i*2+1]
> if bit_pair == 0:
> r.append(complex(1/math.sqrt(2),1/math.sqrt(2)))
> elif bit_pair == 1:
> r.append(complex(1/math.sqrt(2),-1/math.sqrt(2)))
> elif bit_pair == 2:
> r.append(complex(-1/math.sqrt(2),1/math.sqrt(2)))
> elif bit_pair == 3:
> r.append(complex(-1/math.sqrt(2),-1/math.sqrt(2)))
> return r
>
> List comparison: bit_pair as a list before comparison
>
> # QPSK - TS 36.211 V12.2.0, section 7.1.2, Table 7.1.2-1
> def mp_qpsk(self):
> r = []
> for i in range(self.nbits/2):
> bit_pair = self.sbits[i*2:i*2+2]
> if bit_pair == [0,0]:
> r.append()
> elif bit_pair == [0,1]:
> r.append(complex(1/math.sqrt(2),-1/math.sqrt(2)))
> elif bit_pair == [1,0]:
> r.append(complex(-1/math.sqrt(2),1/math.sqrt(2)))
> elif bit_pair == [1,1]:
> r.append(complex(-1/math.sqrt(2),-1/math.sqrt(2)))
> return r
Wrong question. If you are worried about efficiency, factor out all
repeated calculation of constants and eliminate the multiple comparisons.
sbits = self.sbits
a = 1.0 / math.sqrt(2)
b = -a
points = (complex(a,a), complex(a,b), complex(b,a), complex(b,b))
complex(math.sqrt(2),1/math.sqrt(2))
def mp_qpsk(self):
r = [points[sbits[i]*2 + sbits[i+1]]
for i in range(0, self.nbits, 2)]
return r
--
Terry Jan Reedy
[toc] | [prev] | [next] | [standalone]
| From | austin aigbe <eshikafe@gmail.com> |
|---|---|
| Date | 2015-01-04 03:20 -0800 |
| Message-ID | <5499f48c-26e3-41c5-8735-2641fde5f35e@googlegroups.com> |
| In reply to | #83189 |
On Sunday, January 4, 2015 8:12:10 AM UTC+1, Terry Reedy wrote: > On 1/3/2015 6:19 PM, austin aigbe wrote: > > > I am currently implementing the LTE physical layer in Python (ver 2.7.7). > > For the qpsk, 16qam and 64qam modulation I would like to know which is more efficient to use, between an integer comparison and a list comparison: > > > > Integer comparison: bit_pair as an integer value before comparison > > > > # QPSK - TS 36.211 V12.2.0, section 7.1.2, Table 7.1.2-1 > > def mp_qpsk(self): > > r = [] > > for i in range(self.nbits/2): > > bit_pair = (self.sbits[i*2] << 1) | self.sbits[i*2+1] > > if bit_pair == 0: > > r.append(complex(1/math.sqrt(2),1/math.sqrt(2))) > > elif bit_pair == 1: > > r.append(complex(1/math.sqrt(2),-1/math.sqrt(2))) > > elif bit_pair == 2: > > r.append(complex(-1/math.sqrt(2),1/math.sqrt(2))) > > elif bit_pair == 3: > > r.append(complex(-1/math.sqrt(2),-1/math.sqrt(2))) > > return r > > > > List comparison: bit_pair as a list before comparison > > > > # QPSK - TS 36.211 V12.2.0, section 7.1.2, Table 7.1.2-1 > > def mp_qpsk(self): > > r = [] > > for i in range(self.nbits/2): > > bit_pair = self.sbits[i*2:i*2+2] > > if bit_pair == [0,0]: > > r.append() > > elif bit_pair == [0,1]: > > r.append(complex(1/math.sqrt(2),-1/math.sqrt(2))) > > elif bit_pair == [1,0]: > > r.append(complex(-1/math.sqrt(2),1/math.sqrt(2))) > > elif bit_pair == [1,1]: > > r.append(complex(-1/math.sqrt(2),-1/math.sqrt(2))) > > return r > > Wrong question. If you are worried about efficiency, factor out all > repeated calculation of constants and eliminate the multiple comparisons. > > sbits = self.sbits > a = 1.0 / math.sqrt(2) > b = -a > points = (complex(a,a), complex(a,b), complex(b,a), complex(b,b)) > complex(math.sqrt(2),1/math.sqrt(2)) > def mp_qpsk(self): > r = [points[sbits[i]*2 + sbits[i+1]] > for i in range(0, self.nbits, 2)] > return r > > -- > Terry Jan Reedy Cool. Thanks a lot.
[toc] | [prev] | [next] | [standalone]
| From | austin aigbe <eshikafe@gmail.com> |
|---|---|
| Date | 2015-01-04 04:17 -0800 |
| Message-ID | <7968fa1c-9b4c-4d17-9f71-1bbc55392921@googlegroups.com> |
| In reply to | #83194 |
On Sunday, January 4, 2015 12:20:26 PM UTC+1, austin aigbe wrote:
> On Sunday, January 4, 2015 8:12:10 AM UTC+1, Terry Reedy wrote:
> > On 1/3/2015 6:19 PM, austin aigbe wrote:
> >
> > > I am currently implementing the LTE physical layer in Python (ver 2.7.7).
> > > For the qpsk, 16qam and 64qam modulation I would like to know which is more efficient to use, between an integer comparison and a list comparison:
> > >
> > > Integer comparison: bit_pair as an integer value before comparison
> > >
> > > # QPSK - TS 36.211 V12.2.0, section 7.1.2, Table 7.1.2-1
> > > def mp_qpsk(self):
> > > r = []
> > > for i in range(self.nbits/2):
> > > bit_pair = (self.sbits[i*2] << 1) | self.sbits[i*2+1]
> > > if bit_pair == 0:
> > > r.append(complex(1/math.sqrt(2),1/math.sqrt(2)))
> > > elif bit_pair == 1:
> > > r.append(complex(1/math.sqrt(2),-1/math.sqrt(2)))
> > > elif bit_pair == 2:
> > > r.append(complex(-1/math.sqrt(2),1/math.sqrt(2)))
> > > elif bit_pair == 3:
> > > r.append(complex(-1/math.sqrt(2),-1/math.sqrt(2)))
> > > return r
> > >
> > > List comparison: bit_pair as a list before comparison
> > >
> > > # QPSK - TS 36.211 V12.2.0, section 7.1.2, Table 7.1.2-1
> > > def mp_qpsk(self):
> > > r = []
> > > for i in range(self.nbits/2):
> > > bit_pair = self.sbits[i*2:i*2+2]
> > > if bit_pair == [0,0]:
> > > r.append()
> > > elif bit_pair == [0,1]:
> > > r.append(complex(1/math.sqrt(2),-1/math.sqrt(2)))
> > > elif bit_pair == [1,0]:
> > > r.append(complex(-1/math.sqrt(2),1/math.sqrt(2)))
> > > elif bit_pair == [1,1]:
> > > r.append(complex(-1/math.sqrt(2),-1/math.sqrt(2)))
> > > return r
> >
> > Wrong question. If you are worried about efficiency, factor out all
> > repeated calculation of constants and eliminate the multiple comparisons.
> >
> > sbits = self.sbits
> > a = 1.0 / math.sqrt(2)
> > b = -a
> > points = (complex(a,a), complex(a,b), complex(b,a), complex(b,b))
> > complex(math.sqrt(2),1/math.sqrt(2))
> > def mp_qpsk(self):
> > r = [points[sbits[i]*2 + sbits[i+1]]
> > for i in range(0, self.nbits, 2)]
> > return r
> >
> > --
> > Terry Jan Reedy
>
> Cool. Thanks a lot.
Hi Terry,
No difference between the int and list comparison in terms of the number of calls(24) and time (0.004s). Main part is the repeated call to sqrt().
However, it took a shorter time (0.004s) with 24 function calls than your code (0.005s) which took just 13 function calls to execute.
Why is this?
Integer comparison profile result:
>>> p = pstats.Stats('lte_phy_mod.txt')
>>> p.strip_dirs().sort_stats(-1).print_stats()
Sun Jan 04 12:36:32 2015 lte_phy_mod.txt
24 function calls in 0.004 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.004 0.004 0.004 0.004 lte_phy_layer.py:16(<module>)
1 0.000 0.000 0.000 0.000 lte_phy_layer.py:20(Scrambling)
1 0.000 0.000 0.000 0.000 lte_phy_layer.py:276(LayerMapping)
1 0.000 0.000 0.000 0.000 lte_phy_layer.py:278(Precoding)
1 0.000 0.000 0.000 0.000 lte_phy_layer.py:280(ResourceElementMapping)
1 0.000 0.000 0.000 0.000 lte_phy_layer.py:282(OFDMSignalGenerator)
1 0.000 0.000 0.000 0.000 lte_phy_layer.py:65(Modulation)
1 0.000 0.000 0.000 0.000 lte_phy_layer.py:71(__init__)
1 0.000 0.000 0.000 0.000 lte_phy_layer.py:87(mp_qpsk)
1 0.000 0.000 0.000 0.000 {len}
8 0.000 0.000 0.000 0.000 {math.sqrt}
4 0.000 0.000 0.000 0.000 {method 'append' of 'list' objects}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
1 0.000 0.000 0.000 0.000 {range}
<pstats.Stats instance at 0x028F3F08>
>>>
List comparison:
>>> import pstats
>>> p = pstats.Stats('lte_phy_mod2.txt')
>>> p.strip_dirs().sort_stats(-1).print_stats()
Sun Jan 04 12:57:24 2015 lte_phy_mod2.txt
24 function calls in 0.004 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.004 0.004 0.004 0.004 lte_phy_layer.py:16(<module>)
1 0.000 0.000 0.000 0.000 lte_phy_layer.py:20(Scrambling)
1 0.000 0.000 0.000 0.000 lte_phy_layer.py:276(LayerMapping)
1 0.000 0.000 0.000 0.000 lte_phy_layer.py:278(Precoding)
1 0.000 0.000 0.000 0.000 lte_phy_layer.py:280(ResourceElementMapping)
1 0.000 0.000 0.000 0.000 lte_phy_layer.py:282(OFDMSignalGenerator)
1 0.000 0.000 0.000 0.000 lte_phy_layer.py:65(Modulation)
1 0.000 0.000 0.000 0.000 lte_phy_layer.py:71(__init__)
1 0.000 0.000 0.000 0.000 lte_phy_layer.py:87(mp_qpsk)
1 0.000 0.000 0.000 0.000 {len}
8 0.000 0.000 0.000 0.000 {math.sqrt}
4 0.000 0.000 0.000 0.000 {method 'append' of 'list' objects}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
1 0.000 0.000 0.000 0.000 {range}
<pstats.Stats instance at 0x025E3418>
>>>
Terry's code:
>>> import pstats
>>> p = pstats.Stats('lte_phy_mod3.txt')
>>> p.strip_dirs().sort_stats(-1).print_stats()
Sun Jan 04 13:04:51 2015 lte_phy_mod3.txt
13 function calls in 0.005 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.004 0.004 0.005 0.005 lte_phy_layer.py:16(<module>)
1 0.000 0.000 0.000 0.000 lte_phy_layer.py:20(Scrambling)
1 0.000 0.000 0.000 0.000 lte_phy_layer.py:285(LayerMapping)
1 0.000 0.000 0.000 0.000 lte_phy_layer.py:287(Precoding)
1 0.000 0.000 0.000 0.000 lte_phy_layer.py:289(ResourceElementMapping)
1 0.000 0.000 0.000 0.000 lte_phy_layer.py:291(OFDMSignalGenerator)
1 0.000 0.000 0.000 0.000 lte_phy_layer.py:65(Modulation)
1 0.000 0.000 0.000 0.000 lte_phy_layer.py:71(__init__)
1 0.000 0.000 0.000 0.000 lte_phy_layer.py:87(mp_qpsk)
1 0.000 0.000 0.000 0.000 {len}
1 0.000 0.000 0.000 0.000 {math.sqrt}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
1 0.000 0.000 0.000 0.000 {range}
<pstats.Stats instance at 0x02783418>
>>>
[toc] | [prev] | [next] | [standalone]
| From | Christian Gollwitzer <auriocus@gmx.de> |
|---|---|
| Date | 2015-01-04 13:22 +0100 |
| Message-ID | <m8bb91$2h7$1@dont-email.me> |
| In reply to | #83200 |
Am 04.01.15 um 13:17 schrieb austin aigbe: > However, it took a shorter time (0.004s) with 24 function calls than your code (0.005s) which took just 13 function calls to execute. > Why is this? These times are way too short for conclusive results. Typically, the OS timer operates with a millisecond resolution. You need to run a benchmark at least for a second to get reliable information about timing. INstead of 24 times, call your function 20000 times in loop. Christian
[toc] | [prev] | [next] | [standalone]
| From | Mark Lawrence <breamoreboy@yahoo.co.uk> |
|---|---|
| Date | 2015-01-04 12:30 +0000 |
| Message-ID | <mailman.17371.1420374649.18130.python-list@python.org> |
| In reply to | #83201 |
On 04/01/2015 12:22, Christian Gollwitzer wrote: > Am 04.01.15 um 13:17 schrieb austin aigbe: >> However, it took a shorter time (0.004s) with 24 function calls than > your code (0.005s) which took just 13 function calls to execute. > >> Why is this? > > These times are way too short for conclusive results. Typically, the OS > timer operates with a millisecond resolution. You need to run a > benchmark at least for a second to get reliable information about > timing. INstead of 24 times, call your function 20000 times in loop. > > Christian > Maybe using a custom built tool such as https://docs.python.org/3/library/timeit.html#module-timeit ? -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2015-01-04 23:25 +1100 |
| Message-ID | <mailman.17370.1420374349.18130.python-list@python.org> |
| In reply to | #83200 |
On Sun, Jan 4, 2015 at 11:17 PM, austin aigbe <eshikafe@gmail.com> wrote: > However, it took a shorter time (0.004s) with 24 function calls than your code (0.005s) which took just 13 function calls to execute. > > Why is this? That looks to me like noise in your stats. One ULP in timing stats? Not something to base *anything* on. ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Jonas Wielicki <jonas@wielicki.name> |
|---|---|
| Date | 2015-01-04 13:24 +0100 |
| Message-ID | <mailman.17390.1420459599.18130.python-list@python.org> |
| In reply to | #83200 |
On 04.01.2015 13:17, austin aigbe wrote > Hi Terry, > > No difference between the int and list comparison in terms of the number of calls(24) and time (0.004s). Main part is the repeated call to sqrt(). > > However, it took a shorter time (0.004s) with 24 function calls than your code (0.005s) which took just 13 function calls to execute. How often did you run your measurement? 4ms is not a whole lot and can easily be skewed by sudden system load or other noise. You should call the function more often and/or repeat the measurement several times before coming to a judgement (except, possibly, that it doesn’t matter). cheers, jwi
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web