### シングルスレッド
from concurrent.futures import ThreadPoolExecutor import time def func(): time.sleep(1) start = time.time() for i in range(8): func() print(time.time() - start)
$ python3 single.py
8.064586639404297
### マルチスレッド(同時に実行)
from concurrent.futures import ThreadPoolExecutor import time def func(): time.sleep(1) start = time.time() with ThreadPoolExecutor(max_workers=4) as e: for i in range(8): e.submit(func) print(time.time() - start)
$ python3 multithread.py
2.0498673915863037
### マルチプロセス(複数のプロセスで同時に処理)
from concurrent.futures import ProcessPoolExecutor import time def func(): time.sleep(1) start = time.time() with ProcessPoolExecutor(max_workers=4) as e: for i in range(8): e.submit(func) print(time.time() - start)
$ python3 multiprocess.py
2.1424620151519775
import os import time import datetime from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor x1, x2, y1, y2 = -1.8, 1.8, -1.8, 1.8 c_real, c_imag = -0.62772, -0.42193 def calculate_z_serial_purepython(maxiter, zs, cs): output = [0] * len(zs) for i in range(len(zs)): n = 0 z = zs[i] c = cs[i] if (i % 100) == 0: time.sleep(0.0001) while abs(z) < 2 and n < maxiter: z = z * z + c n += 1 output[i] = n return output def calc_pure_python(desired_width, max_iterations): x_step = (float(x2 - x1) / float(desired_width)) y_step = (float(y1 - y2) / float(desired_width)) x = [] y = [] ycoord = y2 while ycoord > y1: y.append(ycoord) ycoord += y_step xcoord = x1 while xcoord < x2: x.append(xcoord) xcoord += x_step zs = [] cs = [] for ycoord in y: for xcoord in x: zs.append(complex(xcoord, ycoord)) cs.append(complex(c_real, c_imag)) output = calculate_z_serial_purepython(max_iterations, zs, cs) if __name__ == "__main__": max_workers = os.cpu_count() start = datetime.datetime.now() for i in range(16): calc_pure_python(desired_width=500, max_iterations=100) elapsed = datetime.datetime.now() - start print("SingleThread: {}ms".format(elapsed.seconds*1000 + elapsed.microseconds/1000)) start = datetime.datetime.now() with ThreadPoolExecutor(max_workers=max_workers) as executor: for i in range(16): executor.submit(calc_pure_python, 500, 100) elapsed = datetime.datetime.now() - start print("MultiThread: {}ms".format(elapsed.seconds*1000 + elapsed.microseconds/1000)) # マルチプロセスの場合 start = datetime.datetime.now() with ProcessPoolExecutor(max_workers=max_workers) as executor: for i in range(16): executor.submit(calc_pure_python, 500, 100) elapsed = datetime.datetime.now() - start print("MultiProcess: {}ms".format(elapsed.seconds*1000 + elapsed.microseconds/1000))
$ python3 main.py
SingleThread: 17934.699ms
MultiThread: 11256.051ms
MultiProcess: 8493.925ms
os.cpu_count() でCPUのコアを取得できるんか…
処理に時間がかかる箇所をマルチプロセスで実装すれば良さそうではあるな…