Openacc多卡优化Floyd算法
状态转移方程
常规的Floyd算法目的在于找最短路,状态转移方程为:dis[i,j]=min{dis[i,k]+dis[k,j],dis[i,j]},距离矩阵初始化为正无穷;本实验目的在于找最长路,所以状态转移方程:dis[i,j]=max{dis[i,k]+dis[k,j],dis[i,j]},距离矩阵初始化为负无穷。
优化思路
众所周知Floyd算法的最外层循环k存在dependence,是不能并行的,所以重点在于如何并行内层的两重循环。在之前的实验中我们把内层的i、j两重循环交给了acc gang和vector,看起来似乎没有优化空间了。
其实还有一个优化的方向,那就是将数据分块,不同的显卡负责不同块数据的计算。虽然我们使用的是线性数组,但是你可以将它想象为方阵,方阵的宽高是SIZE,横着把方阵切几刀,这样就有了若干个block,每一个block的高度就是blocksize。
优化的核心思路如下图:
即每张卡并不是齐头并进,而是有先后顺序,通过async来控制异步。
写代码的过程中需要经常思考这样几个问题:
- 我的数据传到了哪里?
- 显卡上计算出了什么数据?
- 显卡上的数据是否回传?
- 计算完成之后哪张显卡有全部计算好的数据?
- ……
有几个小细节需要注意:
- copy的作用是在GPU上申请内存并将CPU数据拷贝到显存,在退出data region的时候会从GPU拷贝数据到CPU。把copy分解便是create、copyin和copyout,copyout在多卡的时候会出现问题,如果最后一次copyout恰巧是从拥有完整计算结果的显卡拷贝,那没有问题,否则就错了。所以在本次实验中我们采用create与copyin的组合。
- 数据不需要更新地太频繁,计算完一个block更新一次就可以。
- data[a:b]的第二个参数是步长而不是终止点。
代码
floyd.cpp
#define INF 1e7 #include <omp.h> #include <openacc.h> #include <math.h> #include <stdio.h> #include <stdlib.h> #include <assert.h> #include <algorithm> using namespace std;inline int index(const int i, const int j) {return i * SIZE + j; }// add your codes begin #define processor 2 // add your codes endint main() {const int size2 = SIZE * SIZE;float *data = new float[size2];for (int i = 0; i < size2; i++) data[i] = -INF;srand(SIZE);for (int i = 0; i < SIZE*20; i++) {int prev = rand() % SIZE;int next = rand() % SIZE;if ((prev == next) || (data[index(prev, next)] > -INF)) {i--;continue;}data[index(prev, next)] = log((rand() % 99 + 1.0) / 100);}double t = omp_get_wtime();// add your codes beginint blocksize=SIZE/processor;omp_set_num_threads(processor);#pragma omp parallel{int my_gpu=omp_get_thread_num();acc_set_device_num(my_gpu,acc_device_nvidia);#pragma acc data copyin(data[0:size2])//不能使用copy{#pragma omp for schedule(static,1)for(int block=0;block<processor;block++){int istart=block*blocksize;int iend=istart+blocksize;for(int k=0;k<SIZE;k++){#pragma acc parallel loop gang worker num_workers(4) vector_length(128) async(block)for(int i=istart;i<iend;i++){#pragma acc loop vectorfor(int j=0;j<SIZE;j++){if(data[index(i,j)]<data[index(i,k)]+data[index(k,j)]){data[index(i,j)]=data[index(i,k)]+data[index(k,j)];} }}}#pragma acc update self(data[istart*SIZE:SIZE*blocksize]) async(block)}#pragma acc wait}}// add your codes end t = omp_get_wtime() - t;printf("time %f %d\n", t, SIZE);for (int i = 0; i < 20; i++) {int prev = rand() % SIZE;int next = rand() % SIZE;if (prev == next) {i--;continue;}printf("test %d %d %f\n", prev, next, data[index(prev, next)]);} }
run.sh(2卡)
source device.sh 2 make clean # timeout 1m time make serial # timeout 1m time make multicore # timeout 1m time make managed # timeout 1m time make optimize timeout 1m time make multidevice
注释掉了serial、multicore、managed、optimize,只编译多卡,这样缩短了等待时间。
运行结果
2卡2线程的话平均运行时间可以达到1.65~1.75左右。
4卡4线程的话平均运行时间可以达到1.45~1.75左右。
写在最后
有问题欢迎在评论区讨论
Openacc多卡优化Floyd算法相关推荐
- 最短路径——Floyd算法及优化(蓝桥杯试题集)
*对最短路径问题以及floyd算法.Dijkstra算法不是很理解的同学请移步前几篇博客~ 题目链接: http://lx.lanqiao.cn/problem.page?gpid=T15 问题描述 ...
- c语言 floyd优化,Floyd(弗洛伊德)算法(C语言)
Floyd算法的介绍 算法的特点 弗洛伊德算法是解决任意两点间的最短路径的一种算法,可以正确处理有向图或有向图或负权(但不可存在负权回路)的最短路径问题,同时也被用于计算有向图的传递闭包. 算法的思路 ...
- 【POJ/算法】 3259 Wormholes(Bellman-Ford算法, SPFA ,FLoyd算法)
Bellman-Ford算法 Bellman-Ford算法的优点是可以发现负圈,缺点是时间复杂度比Dijkstra算法高.而SPFA算法是使用队列优化的Bellman-Ford版本,其在时间复杂度和编 ...
- 【图论专题】Floyd算法及其扩展应用
Floyd的拓展应用: 任意两点最短路 传递闭包 找最小环 恰好经过k条边的最短路(倍增) 题目列表: 题目 算法 AcWing 1125. 牛的旅行 任意两点最短路Floyd AcWing 343. ...
- floyd算法和动态规划
楔子 long long ago就已经知道了Floyd算法,关键代码就4行,也容易记住,上上周又看到了Floyd,都说是动态规划,所以特意去学了一圈动态规划,今天终于又回到了它 状态方程: d[k][ ...
- 最短路最基本算法———Floyd算法
关于floyd算法 算法简介 实现思想 核心代码 后记 一.floyd简介 引自百度百科 在计算机科学中,Floyd-Warshall算法是一种在具有正或负边缘权重(但没有负周期)的加权图中找到最短路 ...
- 【最短路径Floyd算法详解推导过程】看完这篇,你还能不懂Floyd算法?还不会?...
简介 Floyd-Warshall算法(Floyd-Warshall algorithm),是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法,与Dijkstra算法类似.该算法名称以 ...
- 怎么使用计算机算法,浅谈如何在用计算机来更好的实现Floyd算法
[摘 要]本文主要介绍了数学建模中的一个常用的方法(Floyd算法).我们首先介绍了邻接矩阵的定义.其次,阐述了Floyd算法的具体内容以及Floyd算法的改进.最后,给出了Floyd算法的广泛应用, ...
- DP之Warshall算法和Floyd算法
DP之Warshall算法和Floyd算法 上2篇详细分析了动态规划的一些理解,传统的教材上就大概说了下空间换时间,记忆以避免重复计算等. 然后我们在文章中深入的分析和解释了交叠子问题是怎么表现的,最 ...
最新文章
- 解决This application failed to start because no Qt platform plugin could be initialized问题
- 模式窗体 winform 1201
- 【英语学习】【Level 07】U03 Amazing wonders L4 The Qin Dynasty legacy
- 实现IMSI、IMEI查询
- web开发中特殊字符的对应值与转义字符
- div html 下边加横线_css怎么添加下划线?
- [雪峰磁针石博客]软件测试专家工具包2性能测试
- 创建三维零件的DH坐标系
- pix2pixHD总结
- 蔡学镛:文档模板,天使或恶魔?
- 浅谈显著性检测!真的很浅
- 游戏应用快速审核上架
- 伽罗华有限域_伽罗华域(Galois Field,GF,有限域)乘法运算 - MengBoy的专栏 - CSDN博客...
- Leet Code OJ 刷题顺序参考
- 掏库存分享——抖音平台上可以用来当背景音乐的歌曲
- 安装并测试Gitweb
- 到底什么是云原生(Cloud Native)?什么是CNCF(Cloud Native Computing Foundation)
- 网络规划师上午备考知识点(一)(万能协议篇)
- 雷达原理习题【西电】
- AGC012 - E: Camel and Oases