第22講 素数探索を題材としたマルチスレッドプログラミングの学習
第7話 スレッド6の解答例

スレッド6の解答例
#pragma once
#include <math.h>
#include<stdlib.h>
#include<set>
using namespace std;
int N;
int cn1,cn2,cn3,cn4,cn5,cn6;
int s1[25000000],s2[25000000],s3[25000000],s4[25000000],s5[25000000],s6[25000000];

namespace 素数探索6スレッド {
            ・
            ・
            ・
#pragma endregion
  private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
          set<int> s;
          int i,j,cn;
          N=int::Parse(textBox1->Text);
          s.clear();
          s.insert(2);s.insert(3);s.insert(5);s.insert(7);
          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;
          }
          for(i=0;i<cn5;i++){
            s5[i]=0;
            cn5=0;
          }
          for(i=0;i<cn6;i++){
            s6[i]=0;
            cn6=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));
          Thread^ E=gcnew Thread(gcnew ThreadStart(f5));
          Thread^ F=gcnew Thread(gcnew ThreadStart(f6));

          //計算開始
          A->Start();
          B->Start();
          C->Start();
          D->Start();
          E->Start();
          F->Start();

          //スレッドの終了を待つ
          A->Join();
          B->Join();
          C->Join();
          D->Join();
          E->Join();
          F->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]);
          }
          for(i=0;i<=cn5;i++){
            s.insert(s5[i]);
          }
          for(i=0;i<=cn6;i++){
            s.insert(s6[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+cn5+cn6+3){
              for(j=(cn%10)+1;j<10;j++){
                w[j]=L"";
              }
            }
            if(cn%10==9)dataGridView1->Rows->Add(w);
            cn++;
          }
          dataGridView1->Rows->Add(w);
          TimeSpan sa=ow->Subtract(*hj); //経過時間の計算
          w[0]=L"計算時間"; w[1]=sa.TotalSeconds.ToString();
          for(i=2;i<10;i++)w[i]=L"";
          dataGridView1->Rows->Add(w);
          w[0]=L"素数個数"; w[1]=(cn1+cn2+cn3+cn4+cn5+cn6+4).ToString();
          dataGridView1->Rows->Add(w);

       }
       static void f1(){
         for (int i=8; i<=N; i+=7) {
           if(sh(i)){
             s1[cn1]=i;
             cn1++;
           }
         }
       }
       static void f2(){
         for (int i=9; i<=N; i+=7) {
           if(sh(i)){
             s2[cn2]=i;
             cn2++;
           }
         }
       }
       static void f3(){
         for (int i=10; i<=N; i+=7) {
           if(sh(i)){
             s3[cn3]=i;
             cn3++;
           }
         }
       }
       static void f4(){
         for (int i=11; i<=N; i+=7) {
           if(sh(i)){
             s4[cn4]=i;
             cn4++;
           }
         }
       }
       static void f5(){
         for (int i=12; i<=N; i+=7) {
           if(sh(i)){
             s5[cn5]=i;
             cn5++;
           }
         }
       }
       static void f6(){
         for (int i=13; i<=N; i+=7) {
           if(sh(i)){
             s6[cn6]=i;
             cn6++;
           }
         }
       }
       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);
       }
  };
}


ダウンロード用ファイルForm11.h

実験結果

探索範囲 10000 100000 1000000 10000000
4スレッド 0.0156 0.0312 0.159 2.418
6スレッド 0.0624 0.0468 0.2964 2.6208
倍数差 4 1.5 1.864150943 1.083870968

残念ながら、4スレッドの方が速いようです。
私のパソコン4CPUなので、当然かもしれませんね。
将来、8CPUが普通になるといわれていますから、今回作った6スレッドもそのときには生かされるでしょう。

今回の6スレッドにしても、前回の4スレッドにしても素数を作る各関数は
       static void f1(){
         for (int i=8; i<=N; i+=7) {
           if(sh(i)){
             s1[cn1]=i;
             cn1++;
           }
         }
       }
       static void f2(){
         for (int i=9; i<=N; i+=7) {
           if(sh(i)){
             s2[cn2]=i;
             cn2++;
           }
         }
       }
       static void f3(){
         for (int i=10; i<=N; i+=7) {
           if(sh(i)){
             s3[cn3]=i;
             cn3++;
           }
         }
       }
         ・
         ・
         ・
ほぼ同一の構造をもっています。
そこで、次話ではThreadStartの代わりにParameterizedThreadStartを使い、
4つないし6つの関数を1つの関数にまとめます。

第22講第6話へ 第22講第8話へ


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