pythonマルチスレッドthreading

2038 ワード

最近双線形補間のアルゴリズムを見て、自分で以下を実現したいと思って、1つのプログラムを書いて、時間を測って、1080*1564の1枚の証明書の写真を補間resizeを通じて600*800まで15 sかかりました....
そこでthreadingマルチスレッドでやろうと、3つのサブスレッドが3つのチャネルをそれぞれ補間して、速度が3倍になるのではないでしょうか.結局15 sで、本当に納得できず、pythonマルチスレッドについて調べてみたら、やっと分かった
from PIL import Image
from datetime import datetime
import matplotlib.pyplot as plt
import numpy as np 
import math
import os
from threading import Thread
from multiprocessing import Process


img_path = r'C:\Users\king\Pictures\  \    _20190731154219.jpg'
img_arr = np.array(Image.open(img_path), np.uint8)	

target_size = (800, 600, 3)
global resized_img
resized_img = np.zeros(target_size)
cur_size = img_arr.shape
ratio_x, ratio_y = target_size[0] / cur_size[0], target_size[1] / cur_size[1]

def cal(i, j, x, y, c):
	global resized_img
	# print('this is the thread {}'.format(c))

	t_left_x, t_left_y = math.floor(x), math.floor(y)

	p1 = (t_left_x+1 - x)*img_arr[t_left_x, t_left_y, c] + (x - t_left_x)*img_arr[t_left_x+1, t_left_y, c]
	p2 = (t_left_x+1 - x)*img_arr[t_left_x, t_left_y+1, c] + (x - t_left_x)*img_arr[t_left_x+1, t_left_y+1, c]

	v = (t_left_y+1 - y)*p1 + (y - t_left_y)*p2

	resized_img[i, j, c] = v


def bilinear(c):

	a = [cal(i, j, i/ratio_x, j/ratio_y, c) for i in range(target_size[0]) for j in range(target_size[1])]	


if __name__ == '__main__':
	start = datetime.now()
	threads = []
	for c in range(3):
		t = Thread(target=bilinear, args=(c,))
		threads.append(t)
		t.start()		

	for t in threads:
		t.join()
	# print(resized_img)

	end = datetime.now()

	seconds = (end-start).seconds
	print('process cost {}s'.format(seconds))

	resized_show = Image.fromarray(resized_img.astype(np.uint8))
	plt.imshow(resized_show)
	plt.show()

	

pythonの世界ではGIL(Global Interpreter Lock)と言わざるを得ないが,存在するためCPU時間当たり1スレッドしか実行できないため,シングルコアCPU下のpythonマルチスレッドは同時処理のみで並列処理はできない.
pythonでは、GILの解放ロジックは、IOオペレーションまたはticksテクノロジーがしきい値に達すると、GILが解放され、他のスレッドが起動され、GIL上のCPUに競合して実行されます.この競合モードは、先にサービスしたり、短いジョブを優先したり、タイムスライスを回転したりする可能性があります.