我遇到了一個問題,我很難判斷我應該使用哪種同步原語。
我正在創建n個并行執行緒,它們在一個記憶體區域中作業,每個執行緒被分配到該區域的一個特定部分,并且可以獨立于其他執行緒完成其任務。在某些時候,我需要收集所有執行緒的作業結果,這是使用屏障的一個很好的案例,這就是我正在做的事情。
我必須使用n個作業執行緒中的一個來收集它們所有作業的結果,為此,我有以下代碼,緊隨我的執行緒函式中的計算代碼:
if (pthread_barrier_wait(thread_args-> barrier)) {
//只在最后一個通過屏障的執行緒上被呼叫。
//這是我想收集作業執行緒結果的地方。
}
到目前為止還不錯,但現在我被卡住了:上面的代碼是在一個回圈中,因為我希望執行緒在一定數量的回圈旋轉中再次完成作業。我們的想法是,每次pthread_barrier_wait解鎖時,意味著所有執行緒都完成了他們的作業,回圈的下一次迭代/并行作業可以重新開始。
這樣做的問題是,結果收集器塊陳述句不能保證在其他執行緒再次開始在此區域作業之前執行,因此存在一個競賽條件。我正在考慮使用一個UNIX條件變數,就像這樣:
//這段代碼被放置在執行緒入口點函式中,在內部
//一個回圈,其中也包含了進行并行的代碼。
///處理代碼。。
if (pthread_barrier_wait(thread_args-> barrier)) {
//我們鎖定mutex。
pthread_mutex_lock(thread_args->mutex)。
collectAllWork(); //我們處理所有執行緒的作業。
//設定就緒為1。
thread_args->ready = 1。
//我們廣播條件變數并檢查其是否成功。
if (pthread_cond_broadcast(thread_args-> cond)) {
printf("Error while broadcasting
")。)
exit(1)。
}
// We unlock the mutex
pthread_mutex_unlock(thread_args-> mutex)。
} else {
//等待,直到另一個執行緒完成它的作業,所以。
//我們可以再次開始作業。
pthread_mutex_lock(thread_args->mutex)。
while (thread_args->ready == 0) {
pthread_cond_wait(thread_args->cond, thread_args->mutex) 。
}
pthread_mutex_unlock(thread_args->mutex)。
}
這里面有多個問題:
這里面有多個問題。
- 由于某些原因,
pthread_cond_broadcast從未解鎖任何其他在pthread_cond_wait上等待的執行緒,我不知道為什么。 - 如果一個執行緒
pthread_cond_wait在收集器執行緒廣播之后會怎樣?我相信while (thread_args->ready == 0)和thread_args->ready = 1可以防止這種情況,但請看下一點... - 在下一個回圈旋轉中,
ready仍將被設定為1,因此沒有執行緒會再次呼叫pthread_cond_wait。我沒有看到任何地方可以正確地將ready設定為0:如果我在pthread_cond_wait之后的else塊中這樣做,那么即使我已經從if塊中廣播了,也有可能讓另一個還沒有等待的執行緒讀取1并開始等待。
注意,我需要為此使用障礙物。
如何解決這個問題?
我怎樣才能解決這個問題呢?
uj5u.com熱心網友回復:
你可以使用兩個障礙(作業和收集器):
while (true) {
//do work[/span
//每個執行緒都在等待,直到最后一個執行緒完成其作業。
if (pthread_barrier_wait(thread_args-> work_barrier)) {
//只有一個能通過,然后進行收集。
collectAllWork()。
}
//每一個執行緒都會等待,直到收集器到達這個點。
pthread_barrier_wait(thread_args-> collect_barrier)。
}
uj5u.com熱心網友回復:
你可以使用一種雙重緩沖。
每個作業者將有兩個存盤槽來存盤結果。 在障礙之間,作業者將把他們的結果存盤到一個槽中,而收集器將從另一個槽中讀取結果。
這種方法有幾個優點:
這種方法有幾個優點:
- 沒有額外的障礙 沒有條件佇列。
- 沒有鎖定 插槽識別符號甚至不需要是原子的,因為每個執行緒都可以有它自己的副本,并在到達障礙時切換它。
- 性能更強,因為當收集器正在處理另一個槽時,作業者可以作業 。
示范性作業流程:
迭代1.
- 工人寫到槽0 。
- 收集器不做任何事情,因為沒有資料準備好 。
- 所有人都在等待屏障 。
迭代2.
- 作業人寫到槽位1
- 收集器從槽0讀出
- 所有的人都在等待屏障 。
迭代 3.
- 工人寫到0號槽
- 收集器從槽1讀出
- 所有的人都在等待屏障 。
迭代4.
- 進入迭代2
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/318135.html
標籤:
上一篇:使用awk在檔案的開頭添加列
