2012-02-22 6 views
0

私はクラスのためにeratosthenesを使ってプライムシーブプログラムを書いています。私は8つのスレッドがあり、それぞれが番号範囲[1、2^32]のセグメントを担当しています。なんらかの理由で、スレッド配列内のthread [0]がスレッドの作成時に移動する関数にスレッドを渡さないことがあります。他のものはいつも(そう思われる)行います。このコードで何が間違っているか教えてください。しかし、警告ですが、私はC++を学んでいるだけなので、バグの原因と思われる構文エラーなどがあるかもしれません。これに時間を費やして、それをスレッド[0]に絞り込んで、必ずしもそれを関数にするわけではありません。 #defineの値を変更したので、デバッグが簡単になりました。バグはどちらの方法でも起こります。私がプログラムをどのように改善できるかについての他のコメントにはあまり興味がありません。間もなく予定されているので、私はそれをそのまま働かせたいと思っています。本当にありがとう!このコードが一貫してクラッシュするのはなぜですか?

#include <iostream> 
#include <pthread.h> 
#include <string.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <bitset> 
#include <sys/time.h> 
#include <sys/resource.h> 
#include <sched.h> 
#include <vector> 
#include <math.h> 

using namespace std; 

#define NUM_OF_THREADS 8 
#define TWO_TO_THIRTY_SECOND 1000000 //4294967296 
#define SQRT_TWO_TO_THE_THIRTY_SECOND 1000 //65536 
#define TWO_T0_THIRTY_SECOND_OVER_EIGHT 125000 //536870976 

typedef struct { 
    unsigned long composite_to_remove_index; 
    int thread_index; 
    unsigned long prime_number; 
} thread_info_t; 

bitset<TWO_T0_THIRTY_SECOND_OVER_EIGHT> bitmap[NUM_OF_THREADS]; 
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; 
static pthread_t thread[NUM_OF_THREADS]; 


static void * threadFunc(void *arg) 
{ 

    thread_info_t info = *(thread_info_t *)arg; 

    bitmap[info.thread_index][info.composite_to_remove_index] = 1; 
    info.composite_to_remove_index += info.prime_number; 

    int index_to_remove = (int)info.composite_to_remove_index; 

    for(; index_to_remove < TWO_T0_THIRTY_SECOND_OVER_EIGHT; index_to_remove += info.prime_number) 
    { 
     if(bitmap[info.thread_index][index_to_remove] == 0) 
     { 
      bitmap[info.thread_index][index_to_remove] = 1; 
      if(info.thread_index == 0) 
      { 
       cout << "bit " << index_to_remove << ": " << bitmap[info.thread_index][index_to_remove] << "\n"; 
      } 
     } 
    } 

    return NULL; 
} 

int main (int argc, char * argv[]) 
{ 
    int thread_ret_val; 
    vector<unsigned long long> prime_numbers; 
    thread_info_t info; 

    for(unsigned long long i = 2; i < SQRT_TWO_TO_THE_THIRTY_SECOND; i++) 
    { 
     if(bitmap[0][i] == 0) 
     { 
      prime_numbers.push_back(i); 
      info.prime_number = i; 

      for(unsigned long j = 0; j < NUM_OF_THREADS; j++) 
      { 
       if(j == 0) 
        info.composite_to_remove_index = i*2; 
       else 
        info.composite_to_remove_index = (((TWO_TO_THIRTY_SECOND/NUM_OF_THREADS)*j) % i); 
       info.thread_index = (int)j; 


       thread_ret_val = pthread_create(&thread[info.thread_index], NULL, threadFunc, (void*)&info); 
       if(thread_ret_val != 0) 
       { 
        cerr << "create thread error " << strerror(thread_ret_val) << "\n"; 
       } 
      } 

      for(int j = 0; j < NUM_OF_THREADS; j++) 
      { 
       pthread_join(thread[j], NULL); 
      } 
     } 
    } 

    return 1; 
} 
+6

不安定なクラッシュ。それはスレッド_do_です。 –

+0

スタックがクラッシュしたときのスタックは何ですか?私の推測を見ることなく、あなたは同期なしで複数のスレッドでビットマップにアクセスしています。 –

+0

「機能しない」という意味を説明してください。このプログラムは 'NUM_OF_THREADS = 1'のときと同じ動作をしますか?その場合は、デバッガでプログラムをステップ実行するときに表示される内容を記述します。また、この宿題はありますか? – bta

答えて

1

infoすべてのスレッドに渡された構造は、スレッドごとにユニークであることを意味しますが、誤って、ここで、時折スレッド間で共有されます。問題は、infopthread_createへの呼び出しとthreadFuncの開始の間に変更されないことが保証されていることです。 pthread_createを呼び出した後、次の反復でinfoの内容を変更すると、前のスレッドが実際にの最初の行にinfoをコピーすることがあります。

情報構造はstd::vectorで、infoを使用するたびにpthread_createを呼び出します。

+0

aha。それは理にかなっている。もし私がベクトルを作りたくないのであれば、forループの情報構造体を宣言して、すべてのループの後に範囲外に出ることはできないでしょうか? – Marty

+0

最初の行が実行されているときは、構造体が有効でなければなりません。これはループでは保証されません。各スレッドに独自の構造を与えるか、1つの共有構造にアクセスを同期させます。後者はここでは複雑で不必要です。各スレッドは実際には独自の構造を必要とします。プラス側では、スレッド内の構造体をコピーする必要はありません。 'std :: vector'の代わりに、' new'で各情報を作成し、 'threadFunc'へのポインタとして渡し、ポインタとしてそれを使い、関数の最後に' delete'することになります。 – Dialecticus

+0

素晴らしい私はベクトルをやっている。どうもありがとう! – Marty

関連する問題