I'm trying to improve the speed of some python code a bit and therefore trying to move a standard for loop to either a list comprehension or map call:
buf = [0 for i in range(self.numLEDs * 3)]
temp = [0,0,0]
for x in range(self.numLEDs):
r = data[x*3]
g = data[x*3+1]
b = data[x*3+2]
temp[self.c_order[0]] = self.gamma[r]
temp[self.c_order[1]] = self.gamma[g]
temp[self.c_order[2]] = self.gamma[b]
buf[x * 3:x * 3 + 3] = temp
c_order is simply another list, in this case [1,2,0]. It controls the channel order for some RGB pixels. gamma is a list 256 elements long that holds gamma corrected values for each of the 8bit channel values.
What'd I'd like to do is somehow completely remove any use of a standard for loop from this bit of code. I've managed to do it without the channel swap, but with the gamma correction and it's twice as fast. Like this:
corrected = [gamma[i] for i in data]
buf[0:len(corrected)] = corrected
How can I swap the order of list elements as I go without a for loop though?
解决方案
So you need pure python code without any extension library.
To speedup the code:
use local variable in loops.
change for loop to list comprehension.
Here is the code:
class Test(object):
def __init__(self, n):
self.numLEDs = n
self.c_order = [1, 2, 0]
self.gamma = [i // 2 for i in range(256)]
def do1(self, data):
buf = [0 for i in range(self.numLEDs * 3)]
temp = [0,0,0]
for x in range(self.numLEDs):
r = data[x*3]
g = data[x*3+1]
b = data[x*3+2]
temp[self.c_order[0]] = self.gamma[r]
temp[self.c_order[1]] = self.gamma[g]
temp[self.c_order[2]] = self.gamma[b]
buf[x * 3:x * 3 + 3] = temp
return buf
def do2(self, data):
buf = [0] * (self.numLEDs * 3)
gamma = self.gamma
for idx, idx2 in enumerate(self.c_order):
buf[idx2::3] = [gamma[v] for v in data[idx::3]]
return buf
import random
random.seed(0)
N = 1000
t = Test(N)
data = [random.randint(0, 255) for i in range(3*N)]
r1 = t.do1(data)
r2 = t.do2(data)
print r1 == r2 # check the result
%timeit t.do1(data)
%timeit t.do2(data)
the output, it's 6x faster:
True
1000 loops, best of 3: 1.1 ms per loop
10000 loops, best of 3: 176 µs per loop