2

我有一个关于 C 语言 MPI 编程的基本问题。基本上我想要的是有一个主进程产生特定数量的子进程,从所有子进程中收集一些信息(等到所有子进程完成),计算一些metric,基于这个metric,它决定是否必须产生更多的线程......它会一直这样做,直到metric满足某些特定条件。我翻遍了文献,无济于事。如何才能做到这一点?任何指针?

谢谢您的帮助。

礼貌:使用 C 的消息传递接口 (MPI) 简介。在“对数组求和的完整并行程序”中,可以说,“出于某种蹩脚的原因”,我希望主进程对数组的内容求和两次。即在第一次迭代中,主进程启动计算数组总和的从进程,一旦它们完成并且主进程返回值,我想调用主进程来重新调用另一组线程来执行再次计算。为什么下面的代码不起作用?我在产生从属进程的主进程进程周围添加了一个while循环。

  #include <stdio.h>
  #include <mpi.h>

  #define max_rows 100000
  #define send_data_tag 2001
  #define return_data_tag 2002

  int array[max_rows];
  int array2[max_rows];

main(int argc, char **argv) 
 {
   long int sum, partial_sum,number_of_times;

  number_of_times=0;

  MPI_Status status;

  int my_id, root_process, ierr, i, num_rows, num_procs,
     an_id, num_rows_to_receive, avg_rows_per_process, 
     sender, num_rows_received, start_row, end_row, num_rows_to_send;

  /* Now replicte this process to create parallel processes.
   * From this point on, every process executes a seperate copy
   * of this program */

  ierr = MPI_Init(&argc, &argv);

  root_process = 0;

  /* find out MY process ID, and how many processes were started. */

  ierr = MPI_Comm_rank(MPI_COMM_WORLD, &my_id);
  ierr = MPI_Comm_size(MPI_COMM_WORLD, &num_procs);

  if(my_id == root_process) {

     /* I must be the root process, so I will query the user
      * to determine how many numbers to sum. */

     //printf("please enter the number of numbers to sum: ");
     //scanf("%i", &num_rows);

      num_rows=10;

      while (number_of_times<2)
      {

      number_of_times++;
      start_row=0;
      end_row=0;



     if(num_rows > max_rows) {
        printf("Too many numbers.\n");
        exit(1);
     }

     avg_rows_per_process = num_rows / num_procs;

     /* initialize an array */

     for(i = 0; i < num_rows; i++) {
        array[i] = i + 1;
     }

     /* distribute a portion of the bector to each child process */

     for(an_id = 1; an_id < num_procs; an_id++) {
        start_row = an_id*avg_rows_per_process + 1;
        end_row   = (an_id + 1)*avg_rows_per_process;

        if((num_rows - end_row) < avg_rows_per_process)
           end_row = num_rows - 1;

        num_rows_to_send = end_row - start_row + 1;

        ierr = MPI_Send( &num_rows_to_send, 1 , MPI_INT,
              an_id, send_data_tag, MPI_COMM_WORLD);

        ierr = MPI_Send( &array[start_row], num_rows_to_send, MPI_INT,
              an_id, send_data_tag, MPI_COMM_WORLD);
     }

     /* and calculate the sum of the values in the segment assigned
      * to the root process */

     sum = 0;
     for(i = 0; i < avg_rows_per_process + 1; i++) {
        sum += array[i];   
     } 

     printf("sum %i calculated by root process\n", sum);

     /* and, finally, I collet the partial sums from the slave processes, 
      * print them, and add them to the grand sum, and print it */

     for(an_id = 1; an_id < num_procs; an_id++) {

        ierr = MPI_Recv( &partial_sum, 1, MPI_LONG, MPI_ANY_SOURCE,
              return_data_tag, MPI_COMM_WORLD, &status);

        sender = status.MPI_SOURCE;

        printf("Partial sum %i returned from process %i\n", partial_sum, sender);

        sum += partial_sum;
     }

     printf("The grand total is: %i\n", sum);


      }



  }

  else {

     /* I must be a slave process, so I must receive my array segment,
      * storing it in a "local" array, array1. */

     ierr = MPI_Recv( &num_rows_to_receive, 1, MPI_INT, 
           root_process, send_data_tag, MPI_COMM_WORLD, &status);

     ierr = MPI_Recv( &array2, num_rows_to_receive, MPI_INT, 
           root_process, send_data_tag, MPI_COMM_WORLD, &status);

     num_rows_received = num_rows_to_receive;

     /* Calculate the sum of my portion of the array */

     partial_sum = 0;
     for(i = 0; i < num_rows_received; i++) {
        partial_sum += array2[i];
     }

     /* and finally, send my partial sum to hte root process */

     ierr = MPI_Send( &partial_sum, 1, MPI_LONG, root_process, 
           return_data_tag, MPI_COMM_WORLD);
  }


  ierr = MPI_Finalize();
 }
4

2 回答 2

0

MPI-2 标准包括流程管理功能。它在第 5 章中有详细描述。虽然我自己没有使用它,所以也许其他人可能会提供更实用的提示。

于 2012-05-13T04:46:55.167 回答
0

您应该从查看 MPI_Comm_spawn 和集体操作开始。要从旧的子进程收集信息,通常会使用 MPI_Reduce。

这个stackoverflow问题也可能有帮助。

...to spawn more threads...

我猜你的意思是正确的,因为你主要使用“进程”而不是“线程”,但只是为了澄清:MPI 只处理进程而不是线程。

我不确定您对 MPI 的了解程度——让我知道我的回答是否有帮助或者您是否需要更多提示。

于 2012-05-15T12:22:07.923 回答