分块 Floyd-Warshall 算法
HPC Algorithm GraphTheory Cache_opt普通的 Floyd 算法我们都会了。那么并行化的 Floyd 算法如何呢?
朴素并行化
考虑一份经典的 Floyd 代码:
for(int k = 1; k <= N; k++) {
for(int i = 1; i <= N; i++) {
for(int j = 1; j <= N; j++) {
dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
}
}
}
显然我们可以将第三层循环展开,用 SIMD 优化之。或者,第二、三层循环都可以直接 omp parallel。(请读者自行证明第二层循环也可以,因为任意 dis[k][j]
不会被一个比当前 i
更小的 i1
在这一轮的 k
上以 dis[i1][j]
的方式更新)这里给出第三层循环 omp parallel for 的代码:
for(int k = 1; k <= N; k++) {
for(int i = 1; i <= N; i++) {
#pragma omp parallel for
for(int j = 1; j <= N; j++) {
dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
}
}
}
注意到 dis[i][k]
等内存访问比较花费时间,编译器没帮你优化好的话,比如在 -O0
下,性能会不佳。可以利用一些临时变量辅助,减少 dis[i][k]
的寻址时间。这里就不贴代码了。