第22講 素数探索を題材としたマルチスレッドプログラミングの学習
第4話 マルチスレッド化の方針

題材が決定しましたので、いよいよマルチスレッド対応プログラムに挑みます。
問題は、如何にマルチ化するかです。
処理をうまく、分けてそれぞれを各スレッドに担当させるにはどういたらよいでしょうか。
素数の探索という処理をどのように分割したらよいのでしょうか。
実は、事柄によってはマルチスレッド化が難しいものと簡単なものがあります。
素数の探索や数独問題の作成などは、マルチスレッド対応プログラムに適した題材です。
後に挑戦する数独問題作成ソフトでは、最初に解答を作りそこから一つずつ空欄を作っていって、
問題難度が適当なものになったら、データグリッドビューに表示させるようになっています。
私の研究によると、最初の解答の並びによって問題の難度は決まっていて、
解答の並びが同じなら、如何に空欄の作り方を工夫しても、難度を変更することはできません。
もちろん、空欄を増やしていけば問題難度は難しくなるのですが、
空欄を作りすぎると、答えが複数存在するようになってしまうのです。
数独はパズルですから、答えが一つでなければならないのです。
数独問題作成は、難度と解の唯一性という二つの相矛盾する要求に対して答えなければならないのです。
難度と解の唯一性の争いの結果、問題難度は結局解答の並びに規定されてしまうのです。
したがって、例えば超上級の問題を作るのには、何千回も解答の並びを作り直すしかありません。
つまり、試行錯誤をするしか方法がないわけです。
4CPUなら4つのスレッドを立ち上げ、それぞれのスレッドで試行錯誤をすれば、
CPU使用率は100%になって、問題作成の速度は4倍化します。
1人で試行錯誤していたものを4人で試行錯誤するようにしたということです。
数独作成は、まさにマルチスレッドに向いている事象です。

実は、素数探索もマルチスレッド対応プログラムに向いています。
4スレッドにするには、調べる奇数を4つのタイプに分類すればよいのです。
T 5で割ると1余る奇数
U 5で割ると2余る奇数
V 5で割ると3余る奇数
W 5で割ると4余る奇数
この場合、素数5は入っていませんので、これも手動で入れます。
簡単化のため2,3,5は手動で入れて
s[0]=2;s[1]=3;s[2]=5;
としておきます。
4スレッドに分類すると、7以上の素数
7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,・・・
は次のように分類されます。
T 5で割ると1余る奇数 11,31,41,61,71,・・・
U 5で割ると2余る奇数 7,17,37,47,67,97,・・・
V 5で割ると3余る奇数 13,23,43,53,73,83,・・・
W 5で割ると4余る奇数 19,29,59,79,89,・・・
100以下の素数では、T5個,U6個,V6個,W5個と比較的に均等に分けられていることが分かります。

後で、6スレッドにも挑戦します。
そのときは、
T 7で割ると1余る奇数
U 7で割ると2余る奇数
V 7で割ると3余る奇数
W 7で割ると4余る奇数
X 7で割ると5余る奇数
Y 7で割ると6余る奇数
となります。このときは、7は入ってきませんので、7までは
s[0]=2;s[1]=3;s[2]=5;s[3]=7;
と手動で入れます。
今回の分類では、7以上の素数
11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,・・・

T 7で割ると1余る奇数 29,43,71,113,・・・
U 7で割ると2余る奇数 23,37,79,107,・・・
V 7で割ると3余る奇数 17,31,59,73,101・・・,
W 7で割ると4余る奇数 11,53,67,109,・・・
X 7で割ると5余る奇数 19,47,61,89,103,・・・
Y 7で割ると6余る奇数 13,41,83,97,127,・・・
と今度も比較的均等に分けられます。
『素数で割った余りで分ければ比較的均等にグループ分けできる』
と仮説を立てておいて後に、作ったソフトで検証しましょう。
分類に使うものに、偶数を使えないことは明らかです。例えば、6で割って5分類にすると、
T 6で割ると1余る奇数
U 6で割ると2余る奇数
V 6で割ると3余る奇数
W 6で割ると4余る奇数
X 6で割ると5余る奇数
スレッドUとスレッドWは全く仕事がありません。
6で割ると、2または4余る奇数は存在しないからです。
つまり、5スレッドの内2スレッドが全く無駄になります。

尚、4CPUなのに6スレッドと?を思い浮かべている方もいらっしゃるかもしれませんが、
物理的には1CPUであったとしても、実際の運用では非常に多くのCPUがあるかのように振る舞います。 

何もしていない状態でも約千ほどのスレッドが働いています。
Windows自体が、同時にいくつかのソフトを起動できるようになっています。
このようなことはシングルコア(CPUが1つ)の時代からあったわけです。
私はWindowsはVer3.0の時代から使っていますが、
今から約20年前です。その頃は、もちろんマルチコアのパソコンはもちろん売っていません。

1CPUなのに、あたかも非常に多くのCPUを積んでいるかのように振る舞うとは、
より疑問が大きくなってしまったかもしれませんね。
シングルコアなのにマルチタスク(同時に複数の処理を行う)であった理由は、
実は1つのCPUを時間で区切っているのです。
ある時間帯は一太郎を別の時間帯はエクセルを他の時間帯はブラウザをという風に、
時間を区切って、各処理をあたかも同時にしているかのように見せる、
これが実際の運用では非常に多くのCPUがあるかのように振る舞うの意味です。
このように振る舞っているとき、各CPUを論理CPUというのです。
つまり、CPUが物理的に4つであっても、論理的には
(論理的にという言葉に抵抗がある方は、『仮想的には』と言い換えて頂いて結構です。)
何十もCPUを積んでいるというのは、可能なのです。

ですから、6スレッドは全然問題ありません。
6スレッドに挑戦するのは、4スレッドとどちらが速いか実験するためです。


第22講第3話へ 第22講第5話へ



VC++講義第1部へ
vb講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座