Almost :-)

seqBegin() and seqEnd() takes a communicator as a parameter.
So attribute caching is good for performance (only) if more than one
sequence *per communicator* is used in the application.

Cheers,

Gilles

On Sun, Dec 16, 2018 at 11:38 PM 邹海峰 <haifengzou1...@gmail.com> wrote:
>
> Thank you very much for the reply.
>
> According to your explanation and the content from the website, if there is 
> only one sequential execution in the program, then it doesn't matter whether 
> using the attribute. But if there are multiple sequential execution,  each 
> process only needs to use MPI_Comm_dup() once with the help of attribute, 
> instead of duplicating the MPI_COMM_WORLD whenever there is a  sequential 
> execution. Am I right?
>
> Best wishes!
>
> Gilles Gouaillardet <gilles.gouaillar...@gmail.com> 于2018年12月16日周日 上午8:14写道:
>>
>> Hi,
>>
>> Your understanding is incorrect :
>> "Attributes are local to the process and specific to the communicator
>> to which they are attached."
>> (per 
>> https://www.mcs.anl.gov/research/projects/mpi/mpi-standard/mpi-report-1.1/node119.htm)
>>
>> think an attribute is often a pointer, and really bad things can
>> happen if rank 0 uses a pointer that is valid on rank 1,
>> so if attributes were global, they would be virtually unusable.
>>
>> note the comment before the barrier is incorrect. this is a simple
>> barrier and all MPI tasks will block until all of them invoke seqEnd()
>>
>> The main goal of using attributes in this example is to invoke
>> MPI_Comm_dup() once per communicator (instead of once per sequence,
>> since this is an expensive operation).
>>
>>
>> Cheers,
>>
>> Gilles
>> On Sun, Dec 16, 2018 at 1:04 AM 邹海峰 <haifengzou1...@gmail.com> wrote:
>> >
>> > Hi there,
>> >
>> > At first, I think attribute is just like global variable that attached to 
>> > a specific communicator. I can define and set the value on one process, 
>> > then get and modify the value on another process as long as those 
>> > processes belonging to the same communicator. But when I was reading 
>> > chapter 6 of the book using mpi: portable parallel programming with the 
>> > message-passing interface.  I was confused by the usage of caching 
>> > attribute.
>> >
>> > The purpose the code is to make the execution sequential. the main 
>> > function is
>> >
>> >   seqBegin( MPI_COMM_WORLD );
>> >   printf( "My rank is %d\n", wrank );
>> >   fflush( stdout );
>> >   seqEnd( MPI_COMM_WORLD );
>> >
>> > which is simple to understand. The program will print the rank in order. 
>> > The defination of the function "seqBegin()" is
>> >
>> > static int seqKeyval = MPI_KEYVAL_INVALID;
>> >
>> > void seqBegin( MPI_Comm comm )
>> > {
>> >   MPI_Comm lcomm;
>> >   int      flag, mysize, myrank;
>> >   seqInfo  *info;
>> >   if (seqKeyval == MPI_KEYVAL_INVALID) {
>> >     MPI_Comm_create_keyval( MPI_NULL_COPY_FN, seqDelFn, &seqKeyval, NULL );
>> >   }
>> >   MPI_Comm_get_attr( comm, seqKeyval, &info, &flag );
>> >   if (!flag) {
>> >     info = (seqInfo *)malloc( sizeof(seqInfo) );
>> >     MPI_Comm_dup( comm, &info->lcomm );
>> >     MPI_Comm_rank( info->lcomm, &myrank );
>> >     MPI_Comm_size( info->lcomm, &mysize );
>> >     info->prevRank = myrank - 1;
>> >     if (info->prevRank < 0)   info->prevRank = MPI_PROC_NULL;
>> >     info->nextRank = myrank + 1;
>> >     if (info->nextRank >= mysize) info->nextRank = MPI_PROC_NULL;
>> >     if (verbose) {
>> >       printf( "seqbegin: prev = %d, next = %d\n",
>> >       info->prevRank, info->nextRank );
>> >     }
>> >     MPI_Comm_set_attr( comm, seqKeyval, info );
>> >   }
>> >   MPI_Recv( NULL, 0, MPI_INT, info->prevRank, 0, info->lcomm,
>> >     MPI_STATUS_IGNORE );
>> > }
>> >
>> > and the defination of function "seqEnd()" is
>> >
>> > void seqEnd( MPI_Comm comm )
>> > {
>> >   seqInfo *info;
>> >   int     flag;
>> >
>> >   /* Sanity check */
>> >   if (seqKeyval == MPI_KEYVAL_INVALID)
>> >     MPI_Abort( MPI_COMM_WORLD, 1 );
>> >   MPI_Comm_get_attr( comm, seqKeyval, &info, &flag );
>> >   if (!info || !flag)
>> >     MPI_Abort( MPI_COMM_WORLD, 1 );
>> >   if (verbose) {
>> >     printf( "seqend: prev = %d, next = %d\n",
>> >     info->prevRank, info->nextRank );
>> >   }
>> >   MPI_Send( NULL, 0, MPI_INT, info->nextRank, 0, info->lcomm );
>> >
>> >   /* Make everyone wait until all have completed their send */
>> >   MPI_Barrier( info->lcomm );
>> > }
>> >
>> > Other details are omitted. In fact, all the codes can be found in 
>> > https://www.mcs.anl.gov/research/projects/mpi/usingmpi/examples-usingmpi/libraries/index.html
>> >  which is provided by the author of the book.
>> >
>> > The program uses send and recv to block the execution. Only if the process 
>> > receive the message from last process, the process can continue to 
>> > execute, otherwise it is blocked, which resulting in the sequential 
>> > execution.  The part I don't understand is in function "seqBegin()". If my 
>> > undertstanding about attribute is right, only one process will enter the 
>> > if condition and set the value of attribute, other processes just get the 
>> > value . Here comes the question: since other processes don't set the 
>> > value, how can they get the prevRank and nextRank of their own.
>> >
>> > The code can be executed as expected. But I still can't get the rational 
>> > behind this and there is little reference about attribute caching, so I 
>> > come here for help. Thank you very much !
>> >
>> > Best Wishes !
>> > _______________________________________________
>> > users mailing list
>> > users@lists.open-mpi.org
>> > https://lists.open-mpi.org/mailman/listinfo/users
>> _______________________________________________
>> users mailing list
>> users@lists.open-mpi.org
>> https://lists.open-mpi.org/mailman/listinfo/users
>
> _______________________________________________
> users mailing list
> users@lists.open-mpi.org
> https://lists.open-mpi.org/mailman/listinfo/users
_______________________________________________
users mailing list
users@lists.open-mpi.org
https://lists.open-mpi.org/mailman/listinfo/users

Reply via email to