问题描述:
给定一个数字字符串,将其各位累加求和,如果和不是一个一位数,则继续将和的各位累加,直到和是一个一位数为止。
串行程序如下:(就是一个简单的递归调用)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define SIZE 1000
char str[SIZE];
void all_sum(char * str);
int main()
{
printf("please input a series of number:");
scanf("%s",str);
all_sum(str);
return 0;
}
void all_sum(char * str)
{
int len;
int i;
int sum=0;
len=strlen(str);
for(i=0;i<len;i++)
{
sum+=str[i]-'0';
}
if(sum>=10)
{
itoa(sum,str,10);
all_sum(str);
}
else
{
printf("the result is: %d\n",sum);
return;
}
}
并行程序如下:(运行环境:MPICH2 + VC6.0)
#define MPICH_SKIP_MPICXX
#include "mpi.h"
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<malloc.h>
#pragma comment (lib, "mpi.lib")
#define SIZE 1000
#define BUF_SIZE 64
char str[SIZE];//for single processor
char buf[BUF_SIZE+1];//for multiple processors
FILE *fp1;//for single processor
FILE *fp2;//for multiple processors
int flag=1;//to terminate the worker processor
int all_sum(char * str);//calculate the sum of a series of integers until the sum is a single number(such as 5)
int buf_read(char * buf, const char * end);//read a length of char from the file
int main(int argc, char *argv[])
{
int myid,numprocs;
int i;
MPI_Status status;
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
MPI_Comm_rank(MPI_COMM_WORLD,&myid);
if (numprocs == 1) //single processors
{
char ch;
int sum;
fp1=fopen("D:\\Program Files\\Microsoft Visual Studio\\MyProjects\\MPI\\collapse_file\\input.txt","r");
if(!fp1)
{
printf("can not open the file!\n");
exit(1);
}
int count=0;
while(ch=fgetc(fp1)!='\n')
count++;
rewind(fp1);
fread(str, 1, count, fp1);
sum=all_sum(str);
printf("the result is: %d\n",sum);
}
else //multiple processors
{
int sum=0;
if (myid == 0)
{
/* Master Process */
/* read a block of chars to buf */
int read;
int allocatedJobs = 0;
int part_sum=0;
fp2=fopen("D:\\Program Files\\Microsoft Visual Studio\\MyProjects\\MPI\\collapse_file\\input.txt","r");
if(!fp2)
{
printf("can not open the file!\n");
exit(1);
}
/* initial allocation */
for(i = 1; i < numprocs; i++)
{
read= buf_read(buf, buf+BUF_SIZE);//read a block, but if the last read was a short item count, don't try to read again
if (read)
{
/* allocate a job to proc i */
allocatedJobs++;
MPI_Send(buf,read,MPI_CHAR,i,99,MPI_COMM_WORLD);
}
else//当模拟的处理器个数很大,而需要处理的数据位数很小时,有些处理器不需要工作,就要考虑如何终止不工作的处理器
{
// send a termination signal to terminate the worker
buf[0]='o';
MPI_Send(buf,BUF_SIZE,MPI_CHAR,i,99,MPI_COMM_WORLD);
}
}
while(allocatedJobs)
{
memset(str,0,SIZE*sizeof(char));
MPI_Recv(str , 1 , MPI_CHAR , MPI_ANY_SOURCE , 99 , MPI_COMM_WORLD , &status);
part_sum=atoi(str);
sum+=part_sum;
allocatedJobs--;
read= buf_read(buf, buf+BUF_SIZE);
if(read)
{
MPI_Send(buf,BUF_SIZE,MPI_CHAR,status.MPI_SOURCE,99,MPI_COMM_WORLD);
allocatedJobs++;
}
else
{
// send a termination signal to terminate the worker
buf[0]='o';
MPI_Send(buf,BUF_SIZE,MPI_CHAR,status.MPI_SOURCE,99,MPI_COMM_WORLD);
}
}
}
else
{
while(flag==1)//之所以要用while循环是考虑到当模拟的处理器个数较小时,每一个模拟的处理器需要多次被分配任务
{
MPI_Recv(buf , BUF_SIZE , MPI_CHAR , 0 , 99 , MPI_COMM_WORLD , &status);
int partitial_sum=0;
char char_partitial_sum;
partitial_sum=all_sum(buf);
char_partitial_sum=partitial_sum+'0';
if(buf[0]>='0'&&buf[0]<='9')//如果buf[0]为数字字符,则说明本worker processor接收到了master processor分配的任务,则本worker processor
//需要向master processor发送部分和的结果
MPI_Send(&char_partitial_sum,1,MPI_CHAR,0,99,MPI_COMM_WORLD);
}
}
if (myid == 0)
{
/* print the output */
itoa(sum,str,10);
sum=all_sum(str);
printf("the result is: %d\n",sum);
}
}
MPI_Finalize();
return 0;
}
int all_sum(char * str)
{
int len;
int i;
int sum=0;
len=strlen(str);
for(i=0;i<len;i++)
{
if(str[i]>='0'&&str[i]<='9')
sum+=str[i]-'0';//将所有的字符转变为数字,然后累加
else//如果遇到非数字字符,则置flag为0,结束worker processor
{
flag=0;
break;
}
}
if(sum>=10)//如果和不是一个一位数,则继续将和的各位累加
{
itoa(sum,str,10);
all_sum(str);
}
else//直到和是一个一位数
{
return sum;
}
}
int buf_read(char * buf, const char * end)
{
int count=0;
count = fread(buf, 1, end - buf, fp2);
if (count > 0 && buf[count - 1] == '\n') {
--count;
}
return count;
}
input.txt如下:
以不同的模拟处理器个数运行程序结果如下:
写这个并行程序时的最大问题就是master processor和worker processor的通信,master processor怎么将任务分配给各个worker processor,不仅要注意MPI_Send和MPI_Recv数目的严格匹配,还要注意MPI_Send和MPI_Recv里面的参数也要严格匹配。