完整代码:

#include <iostream>
#include <ctime>
#include <mpi.h>
#include <omp.h>
#include <cstdlib>
#include <iomanip>
#include <Windows.h>
#include <cmath>
#include <algorithm> using namespace std;
const long double G = 6.67 * pow(10, -11);
const int STAR_NUM = 32;
const int THREAD_NUM = 4;
const long int TIME_STEP = 3600;
const int MAX_PROCESS = 128; struct Star
{
long double x, y, z; // Position
long double vx, vy, vz; // Speed
long double ax, ay, az; // Acceleration
long double nax, nay, naz; // Acceleration of next iteration
long double m; // Mass
}; Star stars[STAR_NUM];
Star temp[STAR_NUM];
Star buffer[STAR_NUM]; void updateNextAcceration(Star& a, Star& b) {
long double dx = a.x - b.x;
long double dy = a.y - b.y;
long double dz = a.z - b.z;
long double r2 = pow(dx, 2) + pow(dy, 2) + pow(dz, 2);
long double A = G * a.m / r2;
long double r = sqrt(r2);
long double k = A / r;
b.nax += k * dx;
b.nay += k * dy;
b.naz += k * dz;
} void updateAcceration(Star& star) {
star.ax = star.nax;
star.ay = star.nay;
star.az = star.naz;
star.nax = 0;
star.nay = 0;
star.naz = 0;
} void updateSpeed(Star& star) {
star.vx += star.ax * TIME_STEP;
star.vy += star.ay * TIME_STEP;
star.vz += star.az * TIME_STEP;
} void updatePosition(Star& star) {
star.x += star.vx * TIME_STEP;
star.y += star.vy * TIME_STEP;
star.z += star.vz * TIME_STEP;
} void print(Star* stars, int num=STAR_NUM) {
cout << setiosflags(ios::left) << setw(4) << "Num" << setw(16) << "x" << setw(16) << "y" << setw(16) << "z"
<< setw(16) << "Speed x" << setw(16) << "Speed y" << setw(16) << "Speed z"
<< setw(16) << "Acceleration x" << setw(16) << "Acceleration y" << setw(16) << "Acceleration z"
<< setw(16) << "Next a x" << setw(16) << "Next a y" << setw(16) << "Next a z"
<< setw(16) << "Mass" << endl;
for (int i = 0; i < num; i++) {
cout << setiosflags(ios::left) << setw(4) << i << setw(16) << stars[i].x << setw(16) << stars[i].y << setw(16) << stars[i].z
<< setw(16) << stars[i].vx << setw(16) << stars[i].vy << setw(16) << stars[i].vz
<< setw(16) << stars[i].ax << setw(16) << stars[i].ay << setw(16) << stars[i].az
<< setw(16) << stars[i].nax << setw(16) << stars[i].nay << setw(16) << stars[i].naz
<< setw(16) << stars[i].m << endl;
}
} int main(int argc, char* argv[]) {
MPI_Init(&argc, &argv);
int rank, size, real_size;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size); real_size = min(STAR_NUM, size);
// 每个进程的工作量
int part = STAR_NUM / real_size;
if (part * real_size < STAR_NUM) part++; // 每个进程的工作量已确定
// 现在要剔除不需要的进程
size = STAR_NUM / part;
if (size * part < STAR_NUM) size++; // 进程数已确定 MPI_Comm COMM_WORLD;
if (rank < size) {
MPI_Comm_split(MPI_COMM_WORLD, 1, rank, &COMM_WORLD);
}else {
MPI_Comm_split(MPI_COMM_WORLD, MPI_UNDEFINED, rank, &COMM_WORLD);
} MPI_Comm_rank(COMM_WORLD, &rank);
MPI_Comm_size(COMM_WORLD, &size);
//int part = STAR_NUM / size;
//if (part * size < STAR_NUM) part++; // Create custome mpi datatype.
const int nitems = 13;
int blocklengths[nitems] = { 1,1,1,1, 1,1, 1,1, 1,1, 1,1,1 };
MPI_Datatype types[nitems] = { MPI_LONG_DOUBLE,MPI_LONG_DOUBLE, MPI_LONG_DOUBLE, MPI_LONG_DOUBLE, MPI_LONG_DOUBLE, MPI_LONG_DOUBLE, MPI_LONG_DOUBLE, MPI_LONG_DOUBLE, MPI_LONG_DOUBLE, MPI_LONG_DOUBLE, MPI_LONG_DOUBLE, MPI_LONG_DOUBLE, MPI_LONG_DOUBLE };
MPI_Datatype MPI_STAR;
MPI_Aint offsets[nitems];
offsets[0] = offsetof(Star, x);
offsets[1] = offsetof(Star, y);
offsets[2] = offsetof(Star, z);
offsets[3] = offsetof(Star, vx);
offsets[4] = offsetof(Star, vy);
offsets[5] = offsetof(Star, vz);
offsets[6] = offsetof(Star, ax);
offsets[7] = offsetof(Star, ay);
offsets[8] = offsetof(Star, az);
offsets[9] = offsetof(Star, nax);
offsets[10] = offsetof(Star, nay);
offsets[11] = offsetof(Star, naz);
offsets[12] = offsetof(Star, m);
MPI_Type_create_struct(nitems, blocklengths, offsets, types, &MPI_STAR);
MPI_Type_commit(&MPI_STAR); omp_set_num_threads(THREAD_NUM); if (rank == 0) {
cout << "Generating origin data..." << endl;
srand(time(NULL));
for (int i = 0; i < STAR_NUM; i++) {
stars[i].m = pow(10, 21) + ((long double)rand() / (RAND_MAX)) * pow(10, 22);
stars[i].x = pow(10, 7) + ((long double)rand() / (RAND_MAX)) * pow(10, 8);
stars[i].y = pow(10, 7) + ((long double)rand() / (RAND_MAX)) * pow(10, 8);
stars[i].z = pow(10, 7) + ((long double)rand() / (RAND_MAX)) * pow(10, 8);
stars[i].vx = 0;
stars[i].vy = 0;
stars[i].vz = 0;
stars[i].ax = 0;
stars[i].ay = 0;
stars[i].az = 0;
stars[i].nax = 0;
stars[i].nay = 0;
stars[i].naz = 0;
}
} MPI_Bcast(&stars, STAR_NUM, MPI_STAR, 0, COMM_WORLD); int loopstart = part * rank;
int loopend = min(STAR_NUM, (rank + 1) * part); while (true)
{
// 利用 OpenMP 加速此循环
#pragma omp parallel for
for (int i = loopstart; i < loopend; i++) {
Star* s = &(stars[i]);
updatePosition(*s);
} // 计算下次的加速度需要来自其他进程的数据
MPI_Request req;
//MPI_Ibcast(&stars, STAR_NUM, MPI_STAR, rank, COMM_WORLD, &req);
//MPI_Gather(&stars, STAR_NUM, MPI_STAR, &temp, STAR_NUM, MPI_STAR, rank, COMM_WORLD);
int start = part * rank;
int end = min(part * (rank + 1), STAR_NUM);
int* displs, * rcounts;
displs = (int*)malloc(size * sizeof(int));
rcounts = (int*)malloc(size * sizeof(int));
for (int i = 0; i < size; i++) {
displs[i] = i * part;
rcounts[i] = end - start;
}
//cout << "rank " << rank << "end - start" << end << " - " << start << endl;
MPI_Gatherv(&stars[start], end - start, MPI_STAR, &temp, rcounts, displs, MPI_STAR, 0, COMM_WORLD); MPI_Bcast(&temp, STAR_NUM, MPI_STAR, 0, COMM_WORLD); // 现在 temp 中存的是更新后的数据
for (int i = loopstart; i < loopend; i++) {
for (int j = 0; j < STAR_NUM; j++) {
if (i == j) continue;
updateNextAcceration(temp[j], stars[i]);
}
} //print(stars);
for (int i = loopstart; i < loopend; i++) {
cout << rank<<" "<<setiosflags(ios::left) << setw(4) << i << setw(16) << stars[i].x << setw(16) << stars[i].y << setw(16) << stars[i].z
<< setw(16) << stars[i].vx << setw(16) << stars[i].vy << setw(16) << stars[i].vz
<< setw(16) << stars[i].ax << setw(16) << stars[i].ay << setw(16) << stars[i].az
<< setw(16) << stars[i].nax << setw(16) << stars[i].nay << setw(16) << stars[i].naz
<< setw(16) << stars[i].m << endl;
} // 利用 OpenMP 加速此循环
#pragma omp parallel for
for (int i = loopstart; i < loopend; i++) {
Star* s = &(stars[i]);
updateAcceration(*s);
} // 利用 OpenMP 加速此循环
#pragma omp parallel for
for (int i = loopstart; i < loopend; i++) {
Star* s = &(stars[i]);
updateSpeed(*s);
}
}
}

运行截图:

基于 MPI/OpenMP 混合编程的大规模多体(N-Body)问题仿真实验的更多相关文章

  1. 基于WebView的混合编程

    近日公司需求变更,以前一个页面是后台返回HTML字段,然后我们直接用webView接收,现在新增一个页面,数据后台返回非HTML,页面跟前面一直,所幸自己会点HTML,所以偷了个懒,自己用代码把数据组 ...

  2. Matlab与.NET基于类型安全的接口混合编程入门

    原文:[原创]Matlab与.NET基于类型安全的接口混合编程入门 如果这些文章对你有用,有帮助,期待更多开源组件介绍,请不要吝啬手中的鼠标. [原创分享]Matlab.NET混编调用Figure窗体 ...

  3. 基于引擎的matlab+vc混合编程的配置

    前段时间在项目中做了一些关于基于引擎的vc+matlab混合编程的工作. 如果你是混合编程新手,我相信使用引擎的方式编程是比较简单快捷的一种方式. 当然这种方法也有其缺点,就是不能脱离matlab运行 ...

  4. 由基于qml,c++的串口调试工具浅谈qml与c++混合编程

    最近在做一个基于sim900 的串口通信工具,基于qml和c++来实现. 首先,对于串口,qt有自带的QSerialPort,可以实现同步,和异步通信,qt creator也有自带的例子,本例子是从其 ...

  5. mpi和cuda混合编程的正确编译

    针对大数据的计算,很多程序通过搭建mpi集群进行加速,并取得了很好的效果.算法内部的加速,当前的并行化趋势是利用GPU显卡进行算法加速.针对并行性非常好的算法,GPU加速效果将远大于集群带来的加速效果 ...

  6. 大数据并行计算利器之MPI/OpenMP

    大数据集群计算利器之MPI/OpenMP ---以连通域标记算法并行化为例 1 背景 图像连通域标记算法是从一幅栅格图像(通常为二值图像)中,将互相邻接(4邻接或8邻接)的具有非背景值的像素集合提取出 ...

  7. Atitit 基于sql编程语言的oo面向对象大规模应用解决方案attilax总结

    Atitit 基于sql编程语言的oo面向对象大规模应用解决方案attilax总结 1. Sql语言应该得到更大的范围的应用,1 1.1. 在小型系统项目中,很适合存储过程写业务逻辑2 1.2. 大型 ...

  8. C和C++混合编程中的extern "C" {}

    引言 在用C++的项目源码中,经常会不可避免的会看到下面的代码: 1 2 3 4 5 6 7 8 9 #ifdef __cplusplus extern "C" { #endif ...

  9. [转载:]C#与Fortran混合编程之本地调用Fortran动态链接库

    前言 C#发展到现在,已是一门相当完善的语言,他基于C语言风格,演化于C++.并依靠强大的.NET底层框架.C#可以用来快速构建桌面及Web应用.然而在我们的实际工作中,尽管C#已经非常完善,但还是不 ...

随机推荐

  1. NOI2008 志愿者招聘

    文化课 + 竞赛双废物又来水题解了. 首先,对于题干中的人,很像网络流中的流量,但是他有一个每天人数的下限,我从网上借鉴(chaoxi)到了两种思路: 把下界限制转化为一条边的流量下界,这样就是最小费 ...

  2. ps查看完整程序执行路径

    在linux下查看进程大家都会想到用 ps -ef|grep ***可是看到的不是全路径,怎么看全路径呢?每个进程启动之后在 /proc下面有一个于pid对应的路径例如:ps -ef|grep jav ...

  3. Graphql Tutorials(Episode 02)

    1.前言 我们在上篇已经了解Graphql的使命以及Graphql的概况,接下来,我们跑起来另外一个Helloworld来开启继续学习. 2.Helloworld(使用Graphql 原生API) 这 ...

  4. 全能扫描王(一款识别率超高的OCR识别APP)

    前言 无论是在工作还是日常生活中,我们都会经常遇到,需要将一些纸质资料上的文字内容变成电子文档进行编辑.这个时候就需要拥有一款好用的手机扫描+OCR文字识别功能的应用了. 随着人工智能的兴起,我们都在 ...

  5. create-react-app 基于ts项目,使用react-router-dom搭建项目

    准备工作 来个react项目 create-react-app 基于TS的项目 ts项目安装后 删除node_modules,重新 yarn install, 不然jsx会报错 安装React-rou ...

  6. [水题日常]UVA1639 糖果(Candy,ACM/ICPC Chengdu 2012)

    今天来尝试了几道数学期望相关的题,这是我认为比较有趣的一道题 这次不废话啦直接开始~ 一句话题意:两个分别装有n个糖果的盒子,每次随机选一个盒子然后拿走一颗糖(选的概率分别是\(p\)和\((1-p) ...

  7. Ribbon提供的负载均衡算法IRule(四)

    一.Ribbon算法的介绍 Ribbon的源码地址:https://github.com/Netflix/ribbon IRule:根据特定算法中从服务器列表中选取一个要访问的服务,Ribbon默认的 ...

  8. 手把手教你使用Python轻松搞定发邮件

    前言 现在生活节奏加快,人们之间交流方式也有了天差地别,为了更加便捷的交流沟通,电子邮件产生了,众所周知,电子邮件其实就是客户端和服务器端发送接受数据一样,他有一个发信和一个收信的功能,电子邮件的通信 ...

  9. EF中使用UnitOfWork

    前言 关于EF5中使用UnitWork,参见另一博文:  https://www.cnblogs.com/masonblog/p/9801162.html 每次提交数据库都会打开一个连接,造成结果是: ...

  10. Redis如何做内存优化?

    1.缩减键值对象 缩减键(key)和值(value)的长度, key长度:如在设计键时,在完整描述业务情况下,键值越短越好. value长度:值对象缩减比较复杂,常见需求是把业务对象序列化成二进制数组 ...