這個問題是關於在C++中實現以下模擬的最佳策略。什麼是更好的實施策略?
我試圖做一個模擬作爲一個物理研究項目的一部分,它基本上追蹤空間節點鏈的動態。每個節點都包含一個位置以及某些參數(局部曲率,速度,到鄰居的距離等),這些參數都會隨時間演化。
每次步驟可以被分解到這四個部分:
- 計算局部參數。值取決於鏈中最近的鄰居。
- 計算全局參數。
- 不斷髮展。根據全局和本地參數以及一些隨機力場,每個節點的位置移動很少。
- 填充。如果兩個連續節點之間的距離達到臨界值,則插入新節點。
(此外,節點可以被卡住,這使他們處於非活動狀態的模擬的其餘部分。與不活躍的鄰居不活動節點的本地參數,不會改變,並且不需要任何更多的計算。)
每個節點包含〜60個字節,我在鏈中有〜100 000個節點,我需要發展大約1 000 000個時間步長的鏈。不過,我希望最大限度地提高這些數字,因爲這會增加我的模擬的準確性,但是在合理的時間(〜小時)內完成模擬的限制。 (約30%的節點將處於非活動狀態)。
我已經開始在C++中將此模擬實現爲雙向鏈表。這看起來很自然,因爲我需要在現有節點之間插入新節點,並且因爲本地參數取決於最近的鄰居。 (我添加了一個額外的指針到下一個活動節點,以避免不必要的計算,每當我遍歷整個鏈時)。我並不是專家,當談到並行化(或編碼)時,我已經玩過OpenMP,我真的很喜歡我如何通過兩行代碼加速獨立操作的循環。我不知道如何讓我的鏈表並行執行,或者它甚至可以工作(?)。所以我有了使用stl向量的想法。在哪裏沒有指向最近鄰居的指針,我可以存儲鄰居的索引並通過標準查找訪問它們。我還可以通過鏈的位置(每第x個時間步)對矢量進行排序,以獲得更好的內存位置。這種方法將允許循環OpenMP方式。
我有點害怕這個想法,因爲我不必處理內存管理。我猜想stl向量的實現比我在列表中處理節點的簡單的'new'和'delete'方式要好得多。我知道我可以用stl list做同樣的事情,但我不喜歡用迭代器訪問最近鄰居的方式。
所以我問你,1337 h4x0r和熟練的程序員,我的模擬會是什麼樣的更好的設計?矢量方法是否勾畫出一個好主意?或者有什麼技巧可以在鏈接列表上播放以使其與OpenMP一起使用?或者我應該考慮一個完全不同的方法?
模擬將運行在8核心和48G內存的計算機上,所以我想我可以交易很多內存的速度。
在此先感謝
編輯: 我需要添加1-2%的新節點每個時間段,所以其存儲的載體,而不指數以最近的鄰居,除非我排序的載體將無法正常工作每一步。
您的本地參數如何本地化,以及如何計算全局屬性? –
@Jonathan Dursi:局部參數是局部的,因爲它們只依賴鏈中最近的鄰居。例如:局部曲率通過擬合三個點(一個節點和它的鄰居)到一個圓來近似。全局參數的例子是鏈長度,連續節點之間的距離之和。這是否回答你的問題? – jonalm
我想我會提及 - 如果你沒有遇到它 - gnu_parallel擴展(MSVC有類似的)。基本上std :: library在後臺與openmp並行。如果你用stl編寫你的循環(例如for_each,accumulate,inner_product等) - 那麼你可以先編寫你的代碼的序列版本(以便正確模擬仿真),然後在幾乎平行的情況下對它進行平行處理(幾乎是因爲你仍然需要讓你的容器 - 但是你實現它們 - 線程安全)。我發現它很有幫助。 http://gcc.gnu.org/onlinedocs/libstdc++/manual/parallel_mode.html – Tom