### シングルスレッド
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のコアを取得できるんか…
処理に時間がかかる箇所をマルチプロセスで実装すれば良さそうではあるな…