实现第5章课件中的梯形积分法的MPI编程熟悉并掌握MPI编程方法,规模自行设定,可探讨不同规模对不同实现方式的影响。
# include
#include
#include
double totalSize = 0.00;//表示总面积
double gap = 0.00;
int total_num = 1000;
double begin_num = 1.000, end_num = 8.0000;
int min(int i, int num);
double f(double x) {
return x * x;
}
double cal(int begin, int size) {
double temp_size = 0.00;
for (int i = begin; i < min(begin + size, total_num); ++i) {
temp_size += (f(begin_num + gap * i) + f(begin_num + gap * (i + 1))) * gap / 2;
}
return temp_size;
}
int min(int i, int num) {
if (i < num) {
return i;
}
return num;
}
void accept_task(int thread_num) {
}
int main(int argc, char *argv[]) {
double buf[10];
gap = (end_num - begin_num) / total_num;
int rank, thread_num;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &thread_num);
//每个线程都分配这么(size*rand)多个任务,主线程不分配
int each_thread_size = total_num / (thread_num - 1) + 1;
if (rank != 0) {
buf[rank] = cal((rank - 1) * each_thread_size, each_thread_size);
MPI_Send(buf + rank, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD);
}
if (rank == 0) {
for (int i = 1; i < thread_num; ++i) {
double temp_size;
MPI_Recv(&temp_size, 1, MPI_DOUBLE, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
totalSize += temp_size;
}
printf("total size: %lf\n", totalSize);
}
MPI_Finalize();
return MPI_SUCCESS;
}
有上述实验结果可知,当规模越大时,计算的数据越加精确
对于课件中“多个数组排序”的任务不均衡案例进行MPI编程实现,规模可自己设定、调整。
#include
#include
#include
#include
#include
#include
using namespace std;
const int ARR_NUM = 100; //固定数组大小
const int ARR_LEN = 4000; //固定数组长度
int seg = 50; //粗颗粒的分配大小
vector<vector<int> > arr(ARR_NUM, vector<int>(ARR_LEN));
void init() {
for (int i = 0; i < ARR_NUM; i++) {
for (int j = 0; j < ARR_LEN; j++)
arr[i][j] = rand() % 100;
}
}
void doTask(int begin) {
for (int i = begin; i < min(begin + seg, ARR_NUM); ++i) {
sort(arr[i].begin(), arr[i].end());
}
}
int main() {
init();
int current_task = 0;//当前的任务
MPI_Init(NULL, NULL);
int rank, thread_num;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &thread_num);
MPI_Status status;
int ready;
bool done = false;
if (rank == 0) {
while (current_task < ARR_NUM) {
//接受任何一个线程的状态
MPI_Recv(&ready, 1, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
MPI_Send(¤t_task, 1, MPI_INT, status.MPI_SOURCE, 0, MPI_COMM_WORLD);
current_task += seg;
}
cout << "all work done!!!!!" << endl;
done = true;
} else {
while (!done) {
int begin;
MPI_Send(&ready, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
MPI_Recv(&begin, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &status);
doTask(begin);
}
}
MPI_Finalize();
return 0;
}
实现高斯消去法解线性方程组的MPI编程,与SSE(或AVX)编程结合,并与Pthread、OpenMP(结合SSE或AVX)版本对比,规模自己设定。
#include
#include
#include
#include
#include
const int n = 1024;//固定矩阵规模,控制变量
const int maxN = n + 1; // 矩阵的最大值
float a[maxN][maxN];
float temp[maxN][maxN];//用于暂时存储a数组中的变量,控制变量唯一
int next_task = 0;
int seg;
int line = 0;//记录当前所依赖的行数
struct timeval startTime, stopTime;// timers
/**
* 根据第i行的元素,消除j行的元素
* @param i 根据的行数
* @param j 要消元的行数
*/
void OMP_elimination(int i, int j) {
//求出相差倍数
float temp = a[j][i] / a[i][i];
//遍历这一行的所有值,将i后面的数值依次减去相对应的值乘以倍数
for (int k = i + 1; k <= n; ++k) {
a[j][k] -= a[i][k] * temp;
}
//第i个为0
a[j][i] = 0.00;
}
//用于矩阵改变数值,为防止数据溢出,随机数的区间为100以内的浮点数
void change() {
srand((unsigned) time(NULL));
for (int i = 0; i < n; i++) {
for (int j = 0; j <= n; j++) {
a[i][j] = (float) (rand() % 10000) / 100.00;
}
}
}
int main(int argc, char *argv[]) {
change();
int rank, thread_num;
gettimeofday(&startTime, NULL);
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &thread_num);
MPI_Status status;
int ready;
bool done = false;
if (rank == 0) {
printf("size : %d\n", n);
for (line = 0; line < n - 1; ++line) {
next_task = line + 1;
seg = (n - next_task) / (thread_num - 1) + 1;
for (int i = 1; i < thread_num; i++) {
int task = (i - 1) * seg + next_task;
MPI_Send(&task, 1, MPI_INT, i, 0, MPI_COMM_WORLD);
}
//等待所有线程
for (int j = 1; j < thread_num; ++j) {
MPI_Recv(&ready, 1, MPI_INT, MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &status);
}
}
printf("all work done!!!!!\n");
done = true;
gettimeofday(&stopTime, NULL);
double trans_mul_time =
(stopTime.tv_sec - startTime.tv_sec) * 1000 + (stopTime.tv_usec - startTime.tv_usec) * 0.001;
printf("time: %lf ms\n", trans_mul_time);
} else {
while (!done) {
int task;
MPI_Recv(&task, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &status);
int min = task + seg < n ? task + seg : n;
for (int i = task; i < min; ++i) {
OMP_elimination(line, i);
}
MPI_Send(&ready, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
}
}
MPI_Finalize();
return 0;
}
当规模为2048时