[英]Sampling conditional distribution OpenMP
我有一個隨機抽取樣本的函數:
Sample sample();
我有一個功能可以檢查樣本是否有效:
bool is_valid(Sample s);
這模擬了條件分布。 現在我想要很多有效的樣本(大多數樣本都無效)。
所以我想用 openMP 並行化這段代碼
vector<Sample> valid_samples;
while(valid_samples.size() < n) {
Sample s = sample();
if(is_valid(s)) {
valid_samples.push_back(s);
}
}
我該怎么做? 我發現的大多數 OpenMP 代碼都是簡單的for
循環,其中迭代次數是在開始時確定的。
sample()
函數有一個
thread_local std::mt19937_64 gen([](){
std::random_device d;
std::uniform_int_distribution<int> dist(0,10000);
return dist(d);
}());
作為隨機數生成器。 如果我假設我的設備具有隨機源,那么它是否有效並且線程保存? 有更好的解決方案嗎?
您可以使用 OpenMP任務並行性。 最簡單的解決方案是將任務定義為單個樣本插入:
vector<Sample> valid_samples(n); // need to be resized to allow access in parallel
void insert_ith(size_t i)
{
do {
valid_samples[i] = sample();
} while (!is_valid(valid_samples[i]));
}
#pragma omp parallel
{
#pragma omp single
{
for (size_t i = 0; i < n; i++)
{
#pragma omp task
insert_ith(i);
}
}
}
請注意,此類單任務單插入映射可能存在性能問題。 首先,會涉及錯誤共享,但可能更糟的是,任務管理有一些開銷,這對於非常小的任務可能很重要。 在這種情況下,補救方法很簡單——不是每個任務一次插入,而是一次插入多個項目,例如 100。通常,合適的數字是一種權衡:越低創建的任務越多 = 開銷越大,越高可能會導致更糟糕的負載平衡。
您需要處理代碼中的關鍵部分,即插入到答案向量中
像這樣的東西應該可以工作(因為沒有給出函數和類型,所以沒有編譯)
// create vector before parallel section because it shall be shared
vector<Sample> valid_samples(n); // set initial size to avoid reallocation
int reached_count = 0;
#pragma omp parallel shared(valid_samples, n, reached_count)
{
while(reached_count < n) { // changed this, see comments for discussion
Sample s = sample(); // I assume this to be thread indepent
if(is_valid(s)) {
#pragma omp critical
{
// check condition again, another thread might have already
// reached maximum number
if(reached_count < n) {
valid_samples.push_back(s);
reached_count = valid_samples.size();
}
}
}
}
}
請注意, sample()
和isvalid(s)
都不在臨界區內,因為我認為這些函數比向量插入要昂貴得多,或者接受率非常低
如果不是這種情況,您可以使用獨立的局部向量並最終合並,但是如果您以某種方式減少同步次數,例如提供固定數量的迭代(至少對於很大一部分)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.