2012-02-22 39 views
0

我正在編寫一個使用eratosthenes'上課的主要篩選程序。我有8個線程正在進行,每個線程負責一段數字範圍[1,2^32]。出於某種原因,有時我的線程數組中的線程[0]不會將其創建到線程創建時的函數。其他人總是(看起來)這樣做。請讓我知道這段代碼有什麼問題。一個警告,但我只是學習C++,所以可能會有語法錯誤等,我認爲這是導致錯誤。花了幾個小時,並縮小到線程[0]並不總是使它的功能。我改變了#define的值,所以調試起來會更容易。 Bug發生任何一種方式。請,我對如何改進該計劃的其他評論不感興趣。它很快就會到期,所以我只想讓它按原樣運行。非常感謝!傳遞給所有線程爲什麼此代碼不一致崩潰?

#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_。 – 2012-02-22 22:43:45

+0

什麼是崩潰時的堆棧?沒有看我的猜測是你在多個線程上訪問位圖而沒有同步。 – 2012-02-22 22:45:40

+0

請解釋你的意思是「不符合功能」。當'NUM_OF_THREADS = 1'時,這個程序是否表現出相同的行爲?如果是這樣,請描述在調試器中逐步執行程序時看到的內容。另外,這功課呢? – bta 2012-02-22 22:49:01

回答

1

info結構,就是要爲每個線程唯一的,但是在這裏線程之間不經意間偶爾共享。問題是info不保證在撥打pthread_createthreadFunc開始之間不變。在調用pthread_create後,您在下一次迭代中更改info的內容,並且可能發生的情況是,只有上一個線程實際上在threadFunc的第一行中複製info

您應該有std::vector的信息結構,並且每次調用pthread_create時不同info

+0

aha。這就說得通了。如果我不想創建一個向量,我不能只是在for循環中聲明信息結構,因此它在每個循環之後超出範圍? – Marty 2012-02-22 23:04:47

+0

執行第一行時,結構必須處於活動狀態,並且不能保證循環。爲每個線程分配自己的結構,或者同步對一個共享結構的訪問。後者在這裏很複雜且不必要。每個線程都需要自己的結構。從正面來看,您不必複製線程中的結構。 'std :: vector'的替代方法是用'new'創建每個信息,將它作爲指向'threadFunc'的指針,將其作爲指針使用,並在函數結束時將其刪除。 – Dialecticus 2012-02-22 23:11:38

+0

太棒了。我正在做一個矢量。非常感謝! – Marty 2012-02-22 23:18:53