次のことを行うコードがあります。
for each file (already read in the RAM):
call a function and obtain a result
add the results up and disply
各ファイルは並行して分析できます。各ファイルを解析する関数は次のとおりです。
# Complexity = 1000*19*19 units of work
def fun(args):
(a, b, p) = args
for itr in range(1000):
for i in range(19):
for j in range(19):
# The following random number generated depends on
# latest values in (i-1, j), (i+1, j), (i, j-1) & (i, j+1)
# cells of latest a and b arrays
u = np.random.rand();
if (u < p):
a[i, j] += -1
else:
b[i, j] += 1
return a+b
multiprocessing
並列処理を実現するためにパッケージを使用しています:
import numpy as np
import time
from multiprocessing import Pool, cpu_count
if __name__ == '__main__':
t = time.time()
pool = Pool(processes=cpu_count())
args = [None]*100
for i in range(100):
a = np.random.randint(2, size=(19, 19))
b = np.random.randint(2, size=(19, 19))
p = np.random.rand()
args[i] = (a, b, p)
result = pool.map(fun, args)
for i in range(2, 100):
result[0] += result[i]
print result[0]
print time.time() - t
の各反復で使用および呼び出しを行う同等のMATLAB
コードを作成しました。parfor
fun
parfor
tic
args = cell(100, 1);
r = cell(100, 1);
parfor i = 1:100
a = randi(2, 19, 19);
b = randi(2, 19, 19);
p = rand();
args{i}.a = a;
args{i}.b = b;
args{i}.p = p;
r{i} = fun(args{i});
end
for i = 2:100
r{1} = r{1} + r{i};
end
disp(r{1});
toc
の実装fun
は次のとおりです。
function [ ret ] = fun( args )
a = args.a;
b = args.b;
p = args.p;
for itr = 1:1000
for i = 1:19
for j = 1:19
u = rand();
if (u < p)
a(i, j) = a(i, j) + -1;
else
b(i, j) = b(i, j) + 1;
end
end
end
end
ret = a + b;
end
MATLAB
プログラムが約 33 ~ 34 秒かかるのに対し、デュアル コア プロセッサでは約 1.5 秒かかりますPython
。これはなぜですか?
編集:多くの回答が、乱数生成をベクトル化する必要があることを示唆しています。実際には、生成される乱数は最新の a および b 2D 配列に依存します。プログラムをシンプルで読みやすくするために、簡単なrand()
呼び出しを行いました。私のプログラムの実際では、(i, j) セルの特定の水平方向および垂直方向に隣接するセルを見て、常に乱数が生成されます。したがって、それをベクトル化することはできません。