我编写了一个使用MPI库(MPICH-2)的程序.这个程序可以找到2到N之间的所有素数,如果我只使用两个进程,它可以很好地工作,但当我指定进程数>2时,它就不会工作了。这个程序效率很低,因为我的目的是比较使用MPI的程序和不使用MPI的程序之间的性能。我有一台双核机器,我在Ubuntu13.10上使用NetBeans 7.4。这个问题是否取决于我的机器的核心数目?我知道调度是由操作系统决定的,但我不知道该怎么想!也许我要放一个MPI_Barrier?我插入了下面的代码和输出,因为您可以看到,当我用超过两个procs调用程序时,会出现一些奇怪的零。
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
int count(int *a, int N){
int b[N];
int i, j, n_prime;
for(i=0; i<N; i++)
b[i] = a[i];
b[0] = b[1] = 0;
for (i=2; i<N; i++) {
b[i] = 1;
for (j=2; j<i; j++)
if (i % j == 0) {
b[i] = 0;
break;
}
}
n_prime = 0;
for (j=2; j<N; j++)
if (b[j]) n_prime++;
return n_prime;
}
int main(int argc, char** argv) {
int size, rank, div;
int N;
int *array;
int i, j, k, check, n_prime, n_prime_loc;
int *sub_array, *prime, *recv_prime, *b, *prime2;
double t1, t2;
if(argc != 2){
printf("Argument error: %s not recognized as argument\n", argv[0]);
return -1;
}
N = atoi(argv[1]);
MPI_Init(NULL, NULL);
t1 = MPI_Wtime();
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
div = N/size; //elements per process
b = (int*) malloc(sizeof(int)*N);
if (b == NULL){
printf("Cannot allocate array 'b'\n");
return -1;
}
n_prime = count(b, N);
/* Dynamic allocation of the arrays */
sub_array = (int*) malloc(sizeof(int)*div);
if (sub_array == NULL){
printf("Cannot allocate array 'sub_array'\n");
return -1;
}
recv_prime = (int*) malloc(sizeof(int)*n_prime);
if (recv_prime == NULL){
printf("Cannot allocate array 'recv_prime'\n");
return -1;
}
array = (int*) malloc(sizeof(int)*N);
if (array == NULL){
printf("Cannot allocate array 'array'\n");
return -1;
}
prime = (int*) malloc(sizeof(int)*n_prime);
if (prime == NULL){
printf("Cannot allocate array 'prime'\n");
return -1;
}
/* Initialization of the array */
for (i=0; i<N; i++)
array[i] = i+1;
for(i=0; i<n_prime; i++)
prime[i] = 0;
for(i=0; i<n_prime; i++)
recv_prime[i] = 0;
/* Process 0 divides the array among the processes */
MPI_Scatter(array, div, MPI_INT, sub_array, div, MPI_INT, 0, MPI_COMM_WORLD);
check = 0; //used to check if we find a divisor
k=0;
for(i=0; i<div; i++){
check = 0;
if (sub_array[i] == 1) continue;
for(j=2; j<sub_array[i]; j++){
if(sub_array[i] % j == 0){
check = 1;
}
}
if (check == 0){ //if we don't find a divisor, the number is prime
prime[k] = sub_array[i];
k++;
}
}
n_prime_loc = 0;
for(i=0; i<n_prime; i++)
if(prime[i]!=0)
n_prime_loc++;
prime2 = (int*) malloc(sizeof(int)*n_prime_loc);
j=0;
for(i=0; i<n_prime; i++){
if(prime[i]==0) continue;
prime2[j] = prime[j];
j++;
}
/* Each process sends its computation to the root process */
MPI_Gather(prime2, n_prime_loc, MPI_INT, recv_prime, n_prime_loc, MPI_INT, 0, MPI_COMM_WORLD);
MPI_Barrier(MPI_COMM_WORLD);
if(rank == 0){
printf("Prime numbers: ");
for(i=0; i<n_prime; i++)
printf("%i ", recv_prime[i]);
printf("\n");
}
/* Free the allocated arrays */
free(b);
free(array);
free(recv_prime);
free(prime);
free(prime2);
free(sub_array);
t2 = MPI_Wtime();
//printf("Computation time for Process %i: %f\n", rank, t2-t1);
MPI_Finalize();
return (EXIT_SUCCESS);
}产出如下:
hino@hino-X51L:~/NetBeansProjects/Prime$ mpiexec -np 10 ./Prime 1000
Prime numbers: 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
101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199
0 0 0 0 211 223 227 229 233 239 241 251 257 263 269 271 277 281 283 293 307 311 313
317 331 337 347 349 353 359 367 373 379 383 389 397 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 401 409 419 421 431 433 439 443 449 457 461 463 467 479 487 491 499 503 509 521
523 541 547 557 563 569 571 577 587 593 599 450 451 452 601 607 613 617 619 631 641
643 647 653 659 661 673 677 683 691 701 709 719 727 733 739 743 751 757 761 769 773
787 797 649 650 485 486
hino@hino-X51L:~/NetBeansProjects/Prime$ mpiexec -np 2 ./Prime 1000
Prime numbers: 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
101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199
211 223 227 229 233 239 241 251 257 263 269 271 277 281 283 293 307 311 313 317 331
337 347 349 353 359 367 373 379 383 389 397 401 409 419 421 431 433 439 443 449 457
461 463 467 479 487 491 499 503 509 521 523 541 547 557 563 569 571 577 587 593 599
601 607 613 617 619 631 641 643 647 653 659 661 673 677 683 691 701 709 719 727 733
739 743 751 757 761 769 773 787 797 809 811 821 823 827 829 839 853 857 859 863 877
881 883 887 907 911 919 929 937 941 947 953 967 971 977 983 991 997 发布于 2014-01-28 16:56:57
快速扫描就会发现这里有一些地方不对:
MPI_SCATTER没有正确分配的数字。但这不是你的问题。MPI_GATHER在接收端有一个问题。这里的问题是,您从每个进程发送n_prime_loc编号,但该值对于每个进程也是不同的。例如,秩0可能找到10个素数,因此它的n_prime_loc值将为10,但在秩1上,可能有25个素数(我知道这些例子不准确,但请坚持)。问题是,由于级别0是MPI_GATHER操作的根,它将使用n_prime_loc的值,这意味着如果另一个进程发送更多排名为0的数字,就会出现问题。您需要生成一个足够大的缓冲区,以保存所有可能的结果并适当地收集结果。或者,您可以选择不使用MPI_GATHER,因为缓冲区的大小是事先不知道的。相反,您可以使用MPI_SEND和MPI_RECV,也可以使用MPI_PROBE来了解缓冲区的大小。你可以让其中任何一个发挥作用。MPI_BARRIER在这里是没用的。由于某种原因,当人们不知道在MPI中做什么时,他们会添加一个MPI_BARRIER。这个函数所做的就是让所有的进程在这一点上等待,直到所有其他的进程到达相同的点。您已经通过调用MPI_GATHER实现了这一点,因为所有其他进程都涉及到该调用。https://stackoverflow.com/questions/21402634
复制相似问题