MPI实现求解10的八次方内素数的个数(版本一)

使用MPI计算素数个数

算法实现所使用的方法:

算法描述
当所要计算的个数达到10的8次方,甚至更多时,一台机器很难胜任这份工作。
使用MPI分布式并行计算可以实现这个目标,原来一个人干的事情现在让很多个人来干,这听上去是一个很美妙的事情。
但是俗话说一个和尚挑水喝,两个和尚抬水喝,三个和尚没水喝。
程序也是如此,使用MPI实现多进程来进行计算,虽然有很多的好处,但是编程的复杂性也提升了不少。

版本一(从2到n给每个进程分配一定的任务来进行计算)

让一个进程来负责协调分配工作,其余的进程听其指挥

使用:

   low_value = 2 + id * (n - 1) / p;
   high_value = 1 + (id + 1) * (n - 1) / p;
   size = high_value - low_value + 1;

来确定每一个进程所分配的最大数和最小数,size来记录本进程所计算的大小。

计算出每一个进程中第一个可以被进程0传过来的素数整除的元素的局部索引,记录与first中。

 if (prime * prime > low_value)
          first = prime * prime - low_value;
 else {
         if (!(low_value % prime)) first = 0;
         else first = prime - (low_value % prime);
      }

整体:

#include "mpi.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>

#define MIN(a, b)  ((a)<(b)?(a):(b))

int main(int argc, char *argv[]) {
    unsigned long int count;        /* Local prime count */
    double elapsed_time; /* Parallel execution time */
    unsigned long int first;        /* Index of first multiple */
    unsigned long int global_count = 0; /* Global prime count */
    unsigned long long int high_value;   /* Highest value on this proc */
    unsigned long int i;
    int id;           /* Process ID number */
    unsigned long int index;        /* Index of current prime */
    unsigned long long int low_value;    /* Lowest value on this proc */
    char *marked;       /* Portion of 2,...,'n' */
    unsigned long long int n;            /* Sieving from 2, ..., 'n' */
    int p;            /* Number of processes */
    unsigned long int proc0_size;   /* Size of proc 0's subarray */
    unsigned long int prime;        /* Current prime */
    unsigned long int size;         /* Elements in 'marked' */

    MPI_Init(&argc, &argv);

    /* Start the timer */

    MPI_Comm_rank(MPI_COMM_WORLD, &id);	//获取进程id
    MPI_Comm_size(MPI_COMM_WORLD, &p);	//获取进程数量
    MPI_Barrier(MPI_COMM_WORLD);		//进行同步
    elapsed_time = -MPI_Wtime();

    if (argc != 2) {
        if (!id) printf("Command line: %s <m>\n", argv[0]);
        MPI_Finalize();
        exit(1);
    }

    n = atoll(argv[1]);		//获取要计算的数

    /* Figure out this process's share of the array, as
       well as the integers represented by the first and
       last array elements 计算这个进程在数组中的份额,以及第一个和最后一个数组元素表示的整数*/
    /*********originalSoution*******/
    low_value = 2 + id * (n - 1) / p;
    high_value = 1 + (id + 1) * (n - 1) / p;
    size = high_value - low_value + 1;

    /* Bail out if all the primes used for sieving are
       not all held by process 0 如果用于筛选的所有质数不都由进程0持有,则退出*/

    proc0_size = (n - 1) / p;

    if ((2 + proc0_size) < (int) sqrt((double) n)) {
        if (!id) printf("Too many processes\n");
        MPI_Finalize();
        exit(1);
    }

    /* Allocate this process's share of the array.分配此进程在数组中的份额 */

    marked = (char *) malloc(size);

    if (marked == NULL) {
        printf("Cannot allocate enough memory\n");
        MPI_Finalize();
        exit(1);
    }

    for (i = 0; i < size; i++) marked[i] = 0;
    if (!id) index = 0;			// !id----->只有0号进程才会执行。
    prime = 2;
    do {
        if (prime * prime > low_value)
            first = prime * prime - low_value;
        else {
            if (!(low_value % prime)) first = 0;
            else first = prime - (low_value % prime);       // 此处在求局部first(数组中第一个可以被prime整除的数)的时候非常巧妙
        }
        for (i = first; i < size; i += prime) marked[i] = 1;		// 将可以被整除的数标记起来
        if (!id) {
            while (marked[++index]);
            prime = index + 2;
        }
        if (p > 1) MPI_Bcast(&prime, 1, MPI_INT, 0, MPI_COMM_WORLD);	// 广播,将一个进程中的数据发送到所有进程
    } while (prime * prime <= n);
    count = 0;
    for (i = 0; i < size; i++)
        if (!marked[i]) count++;    // 统计单个进程中素数的个数,看有多少个0
    if (p > 1)
        MPI_Reduce(&count, &global_count, 1, MPI_INT, MPI_SUM,
                   0, MPI_COMM_WORLD);	// 规约,集合通信,由进程0来计算全局的count

    /* Stop the timer */

    elapsed_time += MPI_Wtime();


    /* Print the results */

    if (!id) {
        printf("The total number of prime: %ld, total time: %10.6f, total node %d\n", global_count, elapsed_time, p);
    }
    MPI_Finalize();
    return 0;

}

虽然知道所有的偶数(除2以外)都不是素数,但是程序还是对所有的偶数都进行了计算,下一个版本将进行优化(不计算偶数)。

本地虚拟机的一个执行:
在这里插入图片描述

输出:(使用了四个核心计算10的八次方)

>>>
0:2-25000000
1:25000001-50000000
2:50000001-75000000
3:75000001-100000000
1:count 1435207
0:count 1565927
2:count 1393170
3:count 1367151
The total number of prime: 5761455, total time:   2.107253, total node 4
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值