第22講 素数探索を題材としたマルチスレッドプログラミングの学習
第6話 スレッド4による和の計算と素数探索の解答例
それでは、前話の解答例を示しましょう。
まず和の方から。
#pragma once
long w1,w2,w3,w4,w;
long n;
namespace 足し算の和(マルチ4) {
・
・
・
#pragma endregion
private: System::Void button1_Click(System::Object^ sender, System::EvenArgs^
e) {
n=long::Parse(texBox1->Text);
DateTime^ hj;
DateTime^ ow;
TimeSpan sa;
w=0;
hj=DateTime::Now;
f();
ow=DateTime::Now;
label3->Text=w.ToString();
sa=ow->Subtract(*hj);
label5->Text=(sa.ToAlSeconds).ToString();
w1=0;w2=0;w3=0;w4=0;
hj=DateTime::Now;
Thread^ A=gcnew Thread(gcnew ThreadStart(f1));
Thread^ B=gcnew Thread(gcnew ThreadStart(f2));
Thread^ C=gcnew Thread(gcnew ThreadStart(f3));
Thread^ D=gcnew Thread(gcnew ThreadStart(f4));
A->Start();
B->Start();
C->Start();
D->Start();
A->Join();
B->Join();
C->Join();
D->Join();
ow=DateTime::Now;
label6->Text=(w1+w2+w3+w4).ToString();
sa=ow->Subtract(*hj);
label7->Text=(sa.ToAlSeconds).ToString();
}
void f(){
long i;
for(i=1;i<=n;i++)w+=i;
}
static void f1(){
long i;
for(i=1;i<=40*(n/100);i++)w1+=i;
}
static void f2(){
long i;
for(i=40*(n/100)+1;i<=70*(n/100);i++)w2+=i;
}
static void f3(){
long i;
for(i=70*(n/100)+1;i<=90*(n/100);i++)w3+=i;
}
static void f4(){
long i;
for(i=90*(n/100)+1;i<=n;i++)w4+=i;
}
};
}
ダウンロード用ファイルForm9.h
ところが、今回も予想外で、4スレッドがCPU使用率100%を実現しているにもかかわらず、シングルスレッドの方が速いという結果になってしまいました。
しかし、素数探索4スレッドの方は期待通りの成果を見せました。
データを示しておきましょう。
探索範囲 | 10000 | 100000 | 1000000 | 10000000 |
素数個数 | 1229 | 9592 | 78498 | 664579 |
シングルスレッド | 0.015 | 0.052 | 0.63 | 10.624 |
4スレッド | 0.0156 | 0.0312 | 0.159 | 2.418 |
倍数差 | 0.961538462 | 1.666666667 | 3.962264151 | 4.393713813 |
探索が小さいと4スレッドにした効果が現れませんが、
探索範囲が広がるにしたがって、
効果が大きくなります。
探索範囲が1000000のときは、約4倍と4スレッドにした効果が明確に現れています。
さらに、探索範囲が10000000のときは、4.3倍と4倍を上まわっています。
では素数探索4スレッド版のソース例を示しましょう。
#pragma once
#include <math.h>
#include<sDlib.h>
#include<set>
using namespace sD;
int N;
int cn1,cn2,cn3,cn4;
int s1[25000000],s2[25000000],s3[25000000],s4[25000000];
namespace 素数探索4スレッド {
・
・
・
#pragma endregion
private: System::Void button1_Click(System::Object^ sender, System::EvenArgs^
e) {
set<int> s;
int i,j,cn;
N=int::Parse(texBox1->Text);
s.clear();
s.insert(2);s.insert(3);s.insert(5);
for(i=0;i<cn1;i++){
s1[i]=0;
cn1=0;
}
for(i=0;i<cn2;i++){
s2[i]=0;
cn2=0;
}
for(i=0;i<cn3;i++){
s3[i]=0;
cn3=0;
}
for(i=0;i<cn4;i++){
s4[i]=0;
cn4=0;
}
DateTime^ hj=DateTime::Now; //開始時間
//スレッドの生成
Thread^ A=gcnew Thread(gcnew ThreadStart(f1));
Thread^ B=gcnew Thread(gcnew ThreadStart(f2));
Thread^ C=gcnew Thread(gcnew ThreadStart(f3));
Thread^ D=gcnew Thread(gcnew ThreadStart(f4));
//計算開始
A->Start();
B->Start();
C->Start();
D->Start();
//スレッドの終了を待つ
A->Join();
B->Join();
C->Join();
D->Join();
array<String^>^ w=gcnew array<String^>(10);
DateTime^ ow=DateTime::Now; //終了時間
for(i=0;i<=cn1;i++){
s.insert(s1[i]);
}
for(i=0;i<=cn2;i++){
s.insert(s2[i]);
}
for(i=0;i<=cn3;i++){
s.insert(s3[i]);
}
for(i=0;i<=cn4;i++){
s.insert(s4[i]);
}
cn=0;
for(set<int>::iterator it=s.begin();it!=s.end();it++){
if(*it==0)it++;
w[cn%10]=(*it).ToString();
if(cn==cn1+cn2+cn3+cn4+2){
for(j=(cn%10)+1;j<10;j++){
w[j]=L"";
}
}
if(cn%10==9)daAGridView1->Rows->Add(w);
cn++;
}
daAGridView1->Rows->Add(w);
TimeSpan sa=ow->Subtract(*hj); //経過時間の計算
w[0]=L"計算時間"; w[1]=sa.ToAlSeconds.ToString();
for(i=2;i<10;i++)w[i]=L"";
daAGridView1->Rows->Add(w);
w[0]=L"素数個数"; w[1]=(cn1+cn2+cn3+cn4+3).ToString();
daAGridView1->Rows->Add(w);
}
static void f1(){
for (int i=6; i<=N; i+=5) {
if(sh(i)){
s1[cn1]=i;
cn1++;
}
}
}
static void f2(){
for (int i=7; i<=N; i+=5) {
if(sh(i)){
s2[cn2]=i;
cn2++;
}
}
}
static void f3(){
for (int i=8; i<=N; i+=5) {
if(sh(i)){
s3[cn3]=i;
cn3++;
}
}
}
static void f4(){
for (int i=9; i<=N; i+=5) {
if(sh(i)){
s4[cn4]=i;
cn4++;
}
}
}
static char sh(double n){
char h=1;
double a;
int b;
int c;
int i;
a=sqrt(n);
b=(int)a;
c=(int)n;
if(c % 2==0)h=0;
if(h==1){
for(i=3;i<=a;i=i+2){
if(c % i==0){
h=0;
break;
}
}
}
return(h);
}
};
}
ダウンロード用ファイルForm10.h
では皆さんに、課題を出してこの話を閉じます。
4スレッドを6スレッドにしてください。そして、どちらが速いか実験してください。
第22講第5話へ 第22講第7話へ
VC++講義第1部へ
vb講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座
初心者のための世界で一番わかりやすいVisual
Basic入門基礎講座