Javascript (Worker_行列積)
■Workerの数を変えて行列同士の積の処理を見る。
前回のモンテカルロで円周率を求めるサンプルでは、Workerでスレッドを複数使って処理速度を速くすることができた。今回、このWorkerの数を変えて処理速度やCPUなど見てみたい。
今回のサンプルはより簡単なものとして、行列同士の積にした。
行列積の考え方は簡単に次のとおり。
2×2の行列

3×3の行列


計算量としては、掛け算、足し算をそれぞれ1、要素をNとした場合、各要素で2N-1(掛け算がN回、足し算がN-1)で、要素がN×NだけあるのでN^2。全体で N^2 * (2N-1) となる。上の2×2では、要素が2で計算量12、3×3では要素3で計算量45となる。
今回はこの計算量部分の演算を下のコードで再現して計算する。各Workerでは、Workerの数で分割した分の計算を行うため、行の指定部分(rowStart, rowEnd)がある。
console.log("worker started");
onmessage = e => {
const { A, B, N, rowStart, rowEnd } = e.data;
const C = new Float64Array((rowEnd - rowStart) * N);
for (let i = rowStart; i < rowEnd; i++) {
for (let j = 0; j < N; j++) {
let sum = 0;
for (let k = 0; k < N; k++) {
sum += A[i * N + k] * B[k * N + j];
}
C[(i - rowStart) * N + j] = sum;
}
}
postMessage("done");
};
N=400の結果。横軸がWorkerの数。縦軸が計算実行のミリ秒。
Workerは1, 2, 4, 7, 8, 9, 12, 16で、それぞれ続けて3回実行。CPUはIntel Core i5-1035G1でコア4、スレッド総数8。

次がN=2000。Nを5倍にすると計算量的には125倍ぐらいになるはず。

いずれもWorker数4が一番速い。CPUのスレッド総数が8なので、その辺りが一番速くなるのではと思ったけど、そうでもないよう。ブラウザのPerformanceタブを見ると指定したWorkerの数だけ作られていることが確認できた。16にしてもきれいに表示されるけど、実際の処理は進んでいないかも。

タスクマネージャーでCPUを見ると、Worker数を上げるほど処理中の使用率が上がっていく。8ぐらいで90%前後(±10)になる。一番速かったWorker数4では、CPU使用率は50‐60%ぐらいだった。
Worker数4が速いことについてChat GPTに聞くと、メモリ帯域で詰まっているのではとのこと(行列積ではメモリの消費が多い)。
ので、前回のもの(モンテカルロの円周率を求める)でWorker数を変えて見てみた。結果が下。総数は20憶回で、Worker数で分割した回数を各Workerで実行。割り切れない場合は1つだけ多めにして調整。

こちらは確かにWorker数8あたりが最も速くなっている。
独立した重い処理とかでは、4や8ぐらいまでスレッドを増やせば処理を速くできそう。

