如何使用多线程python减少执行时间

时间:2016-02-04 10:07:46

标签: python multithreading numpy image-processing

我正在执行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秒)。有什么建议?

任何其他概念或方法(我读过有关多处理的帖子)会大大减少我的执行和处理时间吗?

3 个答案:

答案 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关于如何以最小的努力完成此任务的答案。