2

CでのMPIプログラミングについての基本的な質問があります。基本的に私が欲しいのは、特定の数の子プロセスを生成し、それらすべてからいくつかの情報を収集し(すべての子が終了するまで待機します)、いくつかを計算するマスタープロセスがあることです。メトリックは、このメトリックに基づいて、さらにスレッドを生成する必要があるかどうかを決定します...メトリックが特定の条件を満たすまでこれを実行し続けます。私は文献を検索しましたが、役に立ちませんでした。これはどのように行うことができますか?ポインタはありますか?

助けてくれてありがとう。

礼儀:Cを使用したメッセージパッシングインターフェイス(MPI)の概要。「配列を合計する完全並列プログラム」では、「なんらかの理由で」、マスタープロセスで配列の内容を2回合計する必要があります。つまり、最初の反復で、マスタープロセスは、配列の合計を計算するスレーブプロセスを開始します。それらが完了し、マスタープロセスが値を返したら、マスタープロセスを呼び出して、別のスレッドのセットを再度呼び出して、再び計算。以下のコードが機能しないのはなぜですか?スレーブプロセスを生成するマスタープロセスプロセスの周りに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 に答える