2011-03-01 96 views
1

我在pthreads中實現了一個粒子交互模擬器,並且在我的pthreads代碼中不斷收到分段錯誤。故障發生於下面的循環,每個線程確實在每個時間步長在我thread_routine結束:帶pthreads_mutex的Seg故障

for (int i = first; i < last; i++) 
    { 
      get_id(particles[i], box_id); 
      pthread_mutex_lock(&locks[box_id.x + box_no * box_id.y]); 
      //cout << box_id.x << "," << box_id.y << "," << thread_id << "l" << endl; 
      box[box_id.x][box_id.y].push_back(&particles[i]); 
      //cout << box_id.x << box_id.y << endl; 
      pthread_mutex_unlock(&locks[box_id.x + box_no * box_id.y]); 
    } 

奇怪的是,如果我去掉一個(也無所謂哪一個)或兩者程序按預期運行,沒有錯誤發生(但這顯然會導致性能下降,並不是一個優雅的解決方案),從而提供正確的輸出。

框是一個全局聲明 矢量<矢量<矢量< particle_t *>>>框 表示我的(正方形)結構域的一個分解成箱。

當循環開始時,對於所有i,j,box [i] [j] .size()已被設置爲零,並且該循環應該將粒子放回盒結構中(get_id函數給出正確的結果,我已經檢查)

數組pthread_mutex_t鎖被聲明爲一個全球性的

pthread_mutex_t * locks

和大小由線程0設置和鎖定其他線程之前線程初始化爲0被創建:

locks = (pthread_mutex_t *) malloc(box_no*box_no * sizeof(pthread_mutex_t)); 

for (int i = 0; i < box_no*box_no; i++) 
{ 
    pthread_mutex_init(&locks[i],NULL); 
} 

你知道什麼會導致這種情況嗎?如果處理器的數量設置爲1,代碼也會運行,並且似乎運行的處理器越多,出現seg錯誤的時間越早(它已經在兩個處理器上運行過整個模擬器,但這似乎是一個除外)

感謝

+0

cout不是線程安全的。 – Erik 2011-03-01 20:37:42

+0

當cout被註釋掉時會出現問題 – Simen 2011-03-01 20:42:25

+0

get_id是什麼樣的? – 2011-03-01 20:53:46

回答

1

這只是一個受過教育的猜測,但是基於如果對所有方框使用一個鎖,問題就會消失:push_back必須通過std::allocator模板分配內存。我不認爲allocator是保證線程安全,我不認爲它是保證分區,每個vector,一個。 (底層operator new線程安全的,但allocator通常不會塊切片招數來分攤operator new的成本。)

才適合你使用reserve預分配的空間爲您的所有載體的時間提前,使用一些保守的估計,每個盒子中會有多少粒子會堆積起來?這是我第一次嘗試。

我想嘗試的另一件事是對所有的盒子使用一個鎖,我們知道它的作用,但在for循環之外移動鎖定/解鎖操作,以便每個線程一次存儲所有項目。這可能實際上比你想要做的更快 - 更少的鎖定顛簸。

+0

謝謝,這很有道理。我把「超級鎖」移到了循環外部,這使得事情變得更快(但我猜它不會給我O(n/p)運行時間,我應該得到)。我不希望每個盒子中都有很多粒子,通常是0或1. 5會是一個非常保守的估計。我如何使用儲備預先分配空間?編輯:我想我有很多可用的內存,所以這不應該是一個問題 – Simen 2011-03-01 22:51:26

+0

我不知道,加速應該來自每個線程孤立的處理,對吧?這部分是線程間通信開銷的一部分,因此您的目標是儘可能快地完成它,並且很可能整個數據結構中的一個線程將比O( p)鎖。 – zwol 2011-03-01 22:54:59

+0

我添加了一個鏈接到'vector :: reserve'文檔到我的答案。基本上,你會在線程0的設置階段爲每個內部向量調用它。但是當我說一個保守的估計時,我的意思是你需要保留足夠的空間,以便*不管有多少粒子以框中,'push_back'不必調用分配器。否則,你還沒有消除這個錯誤,你只會讓它不太可能咬人。 – zwol 2011-03-01 22:57:53

0

正確初始化的boxbox[i]載體?你只能說最內層的一組向量被設置。否則,它看起來像box_idxy組件是錯誤的並且運行在您的一個陣列的末尾。

看起來是什麼部分崩潰?

+0

在創建任何其他線程之前,線程0將box和box [i]設置爲box_no(它是由運行時輸入確定的變量)。這(不應該)稍後不會更改。我不確定代碼崩潰的時間,除了它在我上面發佈的循環中。由於代碼在打印時工作正常,很難說清楚。任何調試技巧都被感激地接受 – Simen 2011-03-01 21:00:09