我试图提高一些python代码的速度,因此尝试将标准for循环移动到列表理解或地图调用:
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只是另一个列表,在本例中为[1,2,0]。它控制某些RGB像素的通道顺序。 gamma是256个元素长的列表,用于保存每个8位通道值的伽马校正值。
我想要做的是以某种方式从这段代码中完全删除任何标准for循环的使用。我设法在没有频道交换的情况下完成了这项工作,但是通过伽马校正,它的速度提高了两倍。像这样:
corrected = [gamma[i] for i in data]
buf[0:len(corrected)] = corrected
我如何在没有for循环的情况下交换列表元素的顺序?
答案 0 :(得分:3)
您可以在numpy
中完成所有内容,只需几行,但速度要快一些:
In [69]:
gamma=list(np.random.rand(256))
numLEDs=10
data=list(np.random.randint(0,256,30))
c_order=[0,1,2]
In [70]:
%%timeit
buf = [0 for i in range(numLEDs * 3)]
temp = [0,0,0]
for x in range(numLEDs):
r = data[x*3]
g = data[x*3+1]
b = data[x*3+2]
temp[c_order[0]] = gamma[r]
temp[c_order[1]] = gamma[g]
temp[c_order[2]] = gamma[b]
buf[x * 3:x * 3 + 3] = temp
10000 loops, best of 3: 47.3 µs per loop
In [85]:
gamma=np.array(gamma)
data=np.array(data)
In [86]:
%%timeit
data_array=data.reshape(3, -1, order='F')
np.take(gamma[data_array], c_order, axis=0).ravel(order='F')
10000 loops, best of 3: 38.3 µs per loop
当你有很多LED时,numpy
版本会比loop
版本快得多:
In [98]:
gamma=list(np.random.rand(256))
numLEDs=1000
data=list(np.random.randint(0,256,3000))
c_order=[0,1,2]
In [99]:
%%timeit
buf = [0 for i in range(numLEDs * 3)]
temp = [0,0,0]
for x in range(numLEDs):
r = data[x*3]
g = data[x*3+1]
b = data[x*3+2]
temp[c_order[0]] = gamma[r]
temp[c_order[1]] = gamma[g]
temp[c_order[2]] = gamma[b]
buf[x * 3:x * 3 + 3] = temp
100 loops, best of 3: 4.08 ms per loop
In [100]:
gamma=np.array(gamma)
data=np.array(data)
In [101]:
%%timeit
data_array=data.reshape(3, -1, order='F')
np.take(gamma[data_array], c_order, axis=0).ravel(order='F')
1000 loops, best of 3: 244 µs per loop
答案 1 :(得分:1)
所以你需要没有任何扩展库的纯python代码。
加速代码:
以下是代码:
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)
输出,它快了6倍:
True
1000 loops, best of 3: 1.1 ms per loop
10000 loops, best of 3: 176 µs per loop
答案 2 :(得分:0)
与普遍看法相反,调用map
函数不会给你带来显着的加速。实际上你可能会看到更差的表现。
根据您在此部分代码中花费的时间长短,这可能是将此循环简单地移植到C的完美情况。 See here
确保您在此for循环中花费了大量时间,否则调用C代码的开销将超过任何潜在的性能提升。
如果您决定使用此代码将此代码移植到C:
,请在此处阅读一些可能的替代方案