如何解决如何使用 Open MP 并行化 A* 算法?
我在并行化 A* 算法时遇到问题。我曾尝试将单个 for 循环并行化,但这并没有改善任何东西。实际上串行实现仍然比这个快。你能帮我改进这个或给我一些想法吗?
while(openSet.size() > 0){
PAIR current = {};
int maxVal = INT32_MAX;
int i;
#pragma omp parallel for num_threads(tc) ordered schedule(dynamic,1) private(i) shared(openSet,maxVal,current,fscores)
for(i = 0;i < openSet.size();i++){
if(fscores[openSet[i].x * dim + openSet[i].y] < maxVal){
#pragma omp ordered
maxVal = fscores[openSet[i].x * dim + openSet[i].y];
current = openSet[i];
}
}
if(current.x == xEnd && current.y == yEnd){
elapsed = omp_get_wtime() - start;
//printMat(gscores,dim);
printPath("res.txt",mat,cameFrom,dim,tc);
break;
}
int rm = check_remove(openSet,tc);
openSet.erase(openSet.begin() + rm);
vector<PAIR> neighbours;
if(current.x - 1 >= 0 && mat[(current.x - 1) * dim + current.y] != '1'){
neighbours.push_back(PAIR(current.x - 1,current.y));
}
if (current.y - 1 >= 0 && mat[current.x * dim + (current.y - 1)] != '1'){
neighbours.push_back(PAIR(current.x,current.y - 1));
}
if (current.x + 1 < dim && mat[(current.x + 1) * dim + current.y] != '1'){
neighbours.push_back(PAIR(current.x + 1,current.y));
}
if (current.y + 1 < dim && mat[current.x * dim + (current.y + 1)] != '1'){
neighbours.push_back(PAIR(current.x,current.y + 1));
}
int tentative_gscore;
#pragma omp parallel for num_threads(tc) ordered schedule(dynamic,1) private(i) shared(neighbours,openSet,gscores,fscores,tentative_gscore)
for(i = 0;i < neighbours.size();i++){
tentative_gscore = gscores[current.x * dim + current.y] + 1;
if(tentative_gscore < gscores[neighbours[i].x * dim + neighbours[i].y]){
#pragma omp ordered
cameFrom[neighbours[i].x * dim + neighbours[i].y] = current;
gscores[neighbours[i].x * dim + neighbours[i].y] = tentative_gscore;
fscores[neighbours[i].x * dim + neighbours[i].y] = tentative_gscore + hscore(); //(p.x,p.y,xEnd,yEnd)
if(contains(openSet,neighbours[i]) == false){
openSet.push_back(neighbours[i]);
}
}
}
}
解决方法
在第一个循环中,ordered
子句会导致大量时间浪费,如果您只需要 reduction
,您可以使用 maxVal
来避免这种浪费。但是,由于您还需要 current
,因此您必须手动进行缩减。因此,与其直接查找 maxVal
和 current
,不如为这些变量创建中间向量,即 maxValVector
和 currentVector
。然后,我建议每个线程查找 maxValVector[omp_get_thread_num()]
和 currentVector[omp_get_thread_num()]
。因此,您不需要使用 ordered
子句并且每个线程都知道遇到的最大值。然后,您查看,对所涉及的线程数使用串行迷你循环,从 maxVal
和 current
获取 maxValVector
和 currentVector
。这应该能让您对第一个循环进行更有效的并行化。
在第二个循环中,变量 tentative_gScore
应该是私有的,以保证线程安全。此外,我也不认为这里需要 ordered
子句。不确定 openSet.push_back(neighbours[i]);
是怎么回事,但如果可能的话,这行应该由 atomic
或 critical
子句保护。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。