C MPI - 批量生成多个线程

时间:2012-05-13 02:21:08

标签: c mpi

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

感谢您的帮助。

礼貌:An introduction to the Message Passing Interface (MPI) using C。在“对数组求和的完全并行程序”中,让我们说,“出于某些蹩脚的原因”,我希望主进程将数组的内容相加两次。即在第一次迭代中,主进程启动计算数组总和的从进程,一旦完成并且主进程返回值,我想调用主进程重新调用另一组线程来执行再次计算。为什么下面的代码不起作用?我在主进程进程周围添加了一个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();
 }

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

您应该首先查看MPI_Comm_spawn和集合操作。要从旧子进程收集信息,通常会使用MPI_Reduce。

This stackoverflow question 也可能会有所帮助。

...to spawn more threads...

我猜你的意思是正确的,因为你使用了&#34; process&#34;而不是&#34;线程&#34;主要是,但只是为了澄清:MPI只处理流程而不处理线程。

我不确定你对MPI的了解程度如何 - 如果我的答案有任何帮助或需要更多提示,请告诉我。