简述
对于任意情况下的蝶形求和,本质上和任意的树形求和是一样的。只需要做逻辑上的抽象,假设那些点存在补全就好了,然后再加一个限定条件就ok了
代码
#include<stdio.h>
#include<string.h>
#include<mpi.h>
#pragma warning(disable : 4996)
#define MAX_STRING 100
using namespace std;
#include <fstream>
#include <iostream>
int main(void) {
int len;
double scalar, local_sum = 0;
int comm_sz;
int my_rank;
int divided_len;
int last_divided;
int begin_i;
int oper_N = 2;
MPI_Init(NULL, NULL);
MPI_Comm_size(MPI_COMM_WORLD, &comm_sz);
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
// 只有一个线程的时候不操作
if (comm_sz <= 1) {
MPI_Finalize();
return 0;
}
ifstream cin("D:\\C++\\VS\\repo\\MPI-DEMO\\MPI-DEMO\\input.txt");
cin >> len; // 输入数据长度
divided_len = len / comm_sz;
last_divided = len % comm_sz;
if (my_rank < last_divided) {
divided_len++;
begin_i = my_rank * divided_len;
}
else {
begin_i = (my_rank - last_divided) * divided_len + ((divided_len + 1)* last_divided);
}
// 局部和
for (int i = 0; i < len; ++i) {
cin >> scalar;
if (i < begin_i || i >= begin_i + divided_len) continue;
else {
local_sum += scalar;
}
}
// 假设comm_sz不一定是2的幂
// 蝶形求和
while (oper_N <= comm_sz || (oper_N > comm_sz && oper_N / 2 < comm_sz)) {
// 往前发
if (my_rank % oper_N < oper_N / 2) {
if (my_rank + oper_N / 2 < comm_sz){
MPI_Send(&local_sum, 1, MPI_DOUBLE, my_rank + oper_N / 2, 0, MPI_COMM_WORLD);
MPI_Recv(&scalar, 1, MPI_DOUBLE, my_rank + oper_N / 2, 0, MPI_COMM_WORLD, MPI_STATUSES_IGNORE);
local_sum += scalar;
}
}// 往后发
else if (my_rank % oper_N >= oper_N / 2) {
MPI_Send(&local_sum, 1, MPI_DOUBLE, my_rank - oper_N / 2, 0, MPI_COMM_WORLD);
MPI_Recv(&scalar, 1, MPI_DOUBLE, my_rank - oper_N / 2, 0, MPI_COMM_WORLD, MPI_STATUSES_IGNORE);
local_sum += scalar;
}
oper_N *= 2;
}
if (my_rank == 0) {
cout << local_sum << endl;
}
MPI_Finalize();
return 0;
}