我有以下結構的一些多線程C++代碼:如何實現「軟壁壘」,在多線程C++
do_thread_specific_work();
update_shared_variables();
//checkpoint A
do_thread_specific_work_not_modifying_shared_variables();
//checkpoint B
do_thread_specific_work_requiring_all_threads_have_updated_shared_variables();
接下來檢查站B是如果所有線程都達到只檢查點可能已經開始工作,因此我有「軟障礙」的概念。
通常,多線程庫僅提供所有線程必須在可以繼續之前到達某個點的「硬性障礙」。很顯然,在檢查點B可以使用硬屏障。
使用軟屏障可以導致更好的執行時間,尤其是因爲檢查點A和B之間的工作可能不會在線程之間進行負載平衡(即1慢線程已經到達檢查點A但不是B可能導致所有其他人在檢查點B之前的障礙處等待)。
我試過使用原子來同步的東西,我知道100%的確定性,它不能保證工作。例如使用的openmp語法,並行段之前開始:
shared_thread_counter = num_threads; //known at compile time
#pragma omp flush
然後,在檢查站答:
#pragma omp atomic
shared_thread_counter--;
然後,在檢查點B(使用輪詢):
#pragma omp flush
while (shared_thread_counter > 0) {
usleep(1); //can be removed, but better to limit memory bandwidth
#pragma omp flush
}
I」我設計了一些實驗,在這些實驗中我使用了一個原子來指示它在完成之前的某些操作。實驗可以在大多數時間使用2個線程,但當我有很多線程(如20或30)時會一直失敗。我懷疑這是因爲現代CPU的緩存結構。即使一個線程在執行原子減量之前更新了其他某個值,也不能保證以該順序被另一個線程讀取。考慮另一個值是高速緩存未命中並且原子遞減是高速緩存命中的情況。
那麼回到我的問題,如何正確實施這個「軟屏障」?是否有任何內置功能可以保證這些功能?我更喜歡openmp,但我熟悉大多數其他常見的多線程庫。
作爲一種解決方法,我在檢查點B使用硬屏障,並且重構了我的代碼,使檢查點A和B之間的工作自動地在線程之間進行負載平衡(這在次)。
感謝您的任何建議/見解:)
我很困惑你的問題。如果你在A處有一個硬屏障,那麼A之後的任何代碼(包括B之後的代碼)將僅在每個線程通過該屏障後才執行。 B你需要什麼屏障? – Walter
@Walter在A處使用硬屏障在功能上是正確的,但可能會失去性能。考慮在允許任何線程在A和B之間開始工作之前等待一個慢線程到達A的懲罰(因爲基於我們實際上不需要在A處等待的結構)。 – Jason