开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第19天,点击查看活动详情
素数
素数也叫质数,指在大于1的自然数中,除了1和它本身以外不再有其他因数。例如10以内的素数有2、3、5、7
筛选法求质数
不使用mpi
#include<stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
void main()
{
int N = 100;
char* identifies = (char*)malloc(sizeof(char)*N);
memset(identifies, 0, N);
int i,j,k;
for(i=2;i<=(int)(sqrt(N));i++) //从2-10作为最小值开始筛选
{
for(j=2;j*i<N;j++) //找出最小数的倍数
{
identifies[i*j]=1; //把最小数的倍数赋值1
}
}
for(k=2;k<N;k++) //因为1不是素数,所以从2开始遍历输出素数
{
if(identifies[k]==0) //在a数组中如果数组元素是0,那么相应下标就是素数
{
printf("%4d",k);
}
}
}
运行结果:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
使用MPI方法
MPI计算素数时包括划分计算区域、处理器之间的数据通信(Bcast)、数据收集(Reduce)
#include <stdio.h>
#include <mpi.h>
#include <string.h> //包含memset
#include <stdlib.h>
#define BLOCK_LOW(process_rank, n_numbers, process_number) (n_numbers/process_number*process_rank)
#define BLOCK_HIGH(process_rank, n_numbers, process_number) (n_numbers/process_number*(process_rank+1)-1)
int main(int argc, char** argv) {
MPI_Init(&argc, &argv);
int rank, size, local_size, index; //local_size是划分计算区域
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
//确定计算区域
int n_numbers = 100; //100以内的素数
int low = 1 + BLOCK_LOW(rank, n_numbers, size); //素数从2开始计算
int high = 1 + BLOCK_HIGH(rank, n_numbers, size);
local_size = high - low + 1;
char* mark = (char*)malloc(sizeof(char)*local_size); //使用char节省空间
memset(mark, 0, local_size);
index = 1;
int k = 2;
while (k*k < n_numbers) {
for (int i = low; i <= high; i++) {
if(i%k == 0 && i != k) { //不能删掉自己
mark[i-low] = 1;
}
}
//找下一个素数k
if(!rank) {
while (mark[++index]);
k = index + 1;
}
MPI_Bcast(&k, 1, MPI_INT, 0, MPI_COMM_WORLD); //将素数广播出去
}
int count = 0, global_count = 0;
printf("rank = %d的素数有: ", rank);
for (int i = 0; i < local_size; i++) {
count += 1- mark[i];
if(!mark[i]&& (i+low)!=1) printf("%d ", i+low);
}
printf("\n");
MPI_Reduce(&count, &global_count, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
if (!rank) {
printf("一共有%d个素数\n", global_count-1);
}
MPI_Finalize();
}
宏定义中的BLOCK_LOW和BLOCK_HIGH是为了划分每个进程的计算空间。 MPI_Reduce会收集每个处理器发来的数据,然后更具Operation(这里是MPI_SUM)将其规约成一个数字 建议读者手动敲下代码,这样才能理解每个参数、每行代码的用处。
运行结果:
rank = 0的素数有: 2 3 5 7 11 13 17 19 23
rank = 2的素数有: rank = 1的素数有: 29 31 37 41 43 47
53 59 61 67 71 73
rank = 3的素数有: 79 83 89 97
一共有25个素数