简体   繁体   English

找到最接近的对时的OpenMP竞争条件

[英]OpenMP Race Condition when finding Closest Pair

I'm doing an assignment to find the closest pair between two disjoint sets A and B. I'm using OpenMP to parallelize the recursion of the algorithm, but I am running into some data races. 我正在做一个分配,以找到两个不相交的集合A和B之间最接近的对。我正在使用OpenMP并行化算法的递归,但是我遇到了一些数据争用问题。 I am very new to OpenMP, so I think it has something to do with incorrect privating/sharing of variables. 我对OpenMP非常陌生,因此我认为这与不正确的变量共享/共享有关。 I have put the full algorithm below: 我把完整的算法放在下面:

float OMPParticleSim::efficient_closest_pair(int n, vector<Particle> & p, vector<Particle> & q)
{
// brute force
if(n <= 3) {
    float m = numeric_limits<float>::max();

    for(int i = 0; i < n - 2; i++) {
        for(int j = i + 1; j < n - 1; j++) {
            if((set_A.find(p[i].id) != set_A.end() && set_A.find(p[j].id) != set_A.end()) || (set_B.find(p[i].id) != set_B.end() && set_B.find(p[j].id) != set_B.end())) {
                continue;
            }

            float distsq = pow(p[i].x - p[j].x, 2) + pow(p[i].y - p[j].y, 2) + pow(p[i].z - p[j].z, 2);
            pair<pair<Particle, Particle>, float> pa = make_pair(make_pair(p[i], p[j]), sqrt(distsq));

            #pragma omp critical
            insert(pa);

            m = min(m, distsq);
        }
    }

    return sqrt(m);
}

// copy first ceil(n/2) points of p to pl
vector<Particle> pl;
int ceiling = ceil(n/2);

for(int i = 0; i < ceiling; i++) {
    pl.push_back(p[i]);
}

// copy first ceil(n/2) points of q to ql
vector<Particle> ql;

for(int i = 0; i < ceiling; i++) {
    ql.push_back(q[i]);
}

// copy remaining floor(n/2) points of p to pr
vector<Particle> pr;

for(int i = ceiling; i < p.size(); i++) {
    pr.push_back(p[i]);
}

// copy remaining floor(n/2) points of q to qr
vector<Particle> qr;

for(int i = ceiling; i < q.size(); i++) {
    qr.push_back(p[i]);
}

float dl, dr, d;

#pragma omp task firstprivate(pl, ql, p, q, n) private(dl) shared(closest_pairs)
dl = efficient_closest_pair(ceil(n / 2), pl, ql);

#pragma omp task firstprivate(pl, ql, p, q, n) private(dr) shared(closest_pairs)
dr = efficient_closest_pair(ceil(n / 2), pr, qr);

#pragma omp taskwait
d = min(dl, dr);

float m = p[ceil(n / 2) - 1].x;
vector<Particle> s;

for(int i = 0; i < q.size(); i++) {
    if(fabs(q[i].x - m) < d) {
        s.push_back(Particle(q[i]));
    }
}

int num = s.size();
float dminsq = d * d;

for (int i = 0; i < num - 2; i++) {
    int k = i + 1;

    while(k <= num - 1 && pow(s[k].y - s[i].y, 2) < dminsq) {
        if((set_A.find(s[i].id) != set_A.end() && set_A.find(s[k].id) != set_A.end()) || (set_B.find(s[i].id) != set_B.end() && set_B.find(s[k].id) != set_B.end())) {
            k++;
            continue;
        }

        float dist = pow(s[k].x - s[i].x, 2) + pow(s[k].y - s[i].y, 2) + pow(s[k].z - s[i].z, 2);
        pair<pair<Particle, Particle>, float> pa = make_pair(make_pair(s[i], s[k]), sqrt(dist));

        #pragma omp critical
        insert(pa);

        dminsq = min(dist, dminsq);
        k++;
    }
}

return sqrt(dminsq);
}

The insert method looks like this: insert方法如下所示:

void OMPParticleSim::insert(pair<pair<Particle, Particle>, float> & pair) {
    if(closest_pairs.size() == 0) {
        closest_pairs.push_back(pair);
        return;
    }

    for(int i = 0; i < closest_pairs.size(); ++i) {
        if(closest_pairs[i].second > pair.second) {
            closest_pairs.insert(closest_pairs.begin() + i, 1, pair);
            break;
        }
    }

    if(closest_pairs.size() > k) {
        closest_pairs.pop_back();
    }
}

The start of the parallel region is here: 并行区域的起点在这里:

void OMPParticleSim::do_closest_pair(int num_threads) {
    vector<Particle> p = set;

    // presort on x
    sort(p.begin(), p.end(), sortxomp);

    vector<Particle> q = p;

    // presort on y
    sort(q.begin(), q.end(), sortyomp);
    float cp;

    #pragma omp parallel num_threads(num_threads) 
    {
        #pragma omp single 
        {
            cp = efficient_closest_pair(set.size(), p, q);
        }
    }

    sort(closest_pairs.begin(), closest_pairs.end(), sortpairsomp);
}

All of the results are stored in a list closest_pairs and output to a file. 所有结果都存储在一个最接近的对列表中,并输出到文件中。 The reason I know there are data races is because some of the Particle id's are negative (all of them start positive), and running the program multiple times results in different values being written to the file. 我知道存在数据争用的原因是,某些“粒子ID”为负数(它们都以正数开头),并且多次运行该程序会导致将不同的值写入文件。 Any help would be great! 任何帮助将是巨大的!

错误是应该在任务之间共享dl和dr。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM