我正在执行DCT(在Raspberry Pi中)。我已将图像分成8x8块。最初我在嵌套for循环中执行DCT(没有多线程)。我观察到512x512图像需要大约18秒。 但是,这是具有多线程的代码
#!/usr/bin/env python
from __future__ import print_function,division
import time
start_time = time.time()
import cv2
import numpy as np
import sys
import pylab as plt
import threading
import Queue
from numpy import empty,arange,exp,real,imag,pi
from numpy.fft import rfft,irfft
from pprint import pprint
queue = Queue.Queue()
if len(sys.argv)>1:
im = cv2.imread(sys.argv[1])
else :
im = cv2.imread('baboon.jpg')
im = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
h, w = im.shape[:2]
DF = np.zeros((h,w))
Nb=8
def dct2(y):
M = y.shape[0]
N = y.shape[1]
a = empty([M,N],float)
b = empty([M,N],float)
for i in range(M):
a[i,:] = dct(y[i,:])
for j in range(N):
b[:,j] = dct(a[:,j])
queue.put(b)
def dct(y):
N = len(y)
y2 = empty(2*N,float)
y2[:N] = y[:]
y2[N:] = y[::-1]
c = rfft(y2)
phi = exp(-1j*pi*arange(N)/(2*N))
return real(phi*c[:N])
def Main():
jobs = []
for row in range(0, h, Nb):
for col in range(0, w, Nb):
f = im[(row):(row+Nb), (col):(col+Nb)]
thread = threading.Thread(target=dct2(f))
jobs.append(thread)
df = queue.get()
DF[row:row+Nb, col:col+Nb] = df
for j in jobs:
j.start()
for j in jobs:
j.join()
if __name__ == "__main__":
Main()
cv2.imwrite('dct_img.jpg', DF)
print("--- %s seconds ---" % (time.time() - start_time))
plt.imshow(DF1, cmap = 'Greys')
plt.show()
cv2.waitKey(0)
cv2.destroyAllWindows()
使用多个线程后,此代码大约需要25秒才能执行。怎么了?我是否错误地实现了多线程?我希望尽可能减少执行DCT所需的时间(1-5秒)。有什么建议?
任何其他概念或方法(我读过有关多处理的帖子)会大大减少我的执行和处理时间吗?
答案 0 :(得分:1)
由于GIL所有线程都按顺序执行(不是并行执行)。 所以你可能想切换到multiprocessing。另一种选择是构建numba,其中greatly increase speed of usual python code也可以unlock GIL。
答案 1 :(得分:1)
在Python中,只有在混合IO和CPU任务时才应使用多线程进行性能。
对于您的问题,您应该使用多处理。
答案 2 :(得分:0)
也许其他海报对GIL是正确的。但是OpenCV以及Numpy释放了GIL,所以我至少期望从多线程解决方案中获得加速。
我会看一下你同时创建多少个线程。自从你为每个8乘8像素子画面开始一个以来,这可能很多。 (每次将一个线程从cpu中删除并被另一个线程替换时,它会产生一个小的开销,如果你有很多线程,它总是很明显)
如果是这种情况,你可能会通过不立即启动它们来获得性能,但只能启动尽可能多的cpu内核(少了几个......只是实验)并且只启动下一个线程一个人已经完成了。
查看this question关于如何以最小的努力完成此任务的答案。