<div dir="ltr">Thanks.  I think this is a reasonable conclusion.  One might expect an implementation that does this to expose control of internal concurrency by environment variables (or that fancy MPI_T business about which I know almost nothing) so as to ensure an "evil" user only blows their leg off once.<div><br></div><div>Best,</div><div><br></div><div>Jeff</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Oct 20, 2015 at 11:19 AM, William Gropp <span dir="ltr"><<a href="mailto:wgropp@illinois.edu" target="_blank">wgropp@illinois.edu</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">The standard doesn’t explicitly address this.<br>
<br>
However, in the spirit of the standard, I would say yes, multiple threads may be used.  The behavior of side effects of the function are not defined, nor is it required to apply to elements 0..n-1 in that order in an n-element vector (this is a vector on each process; the is/is-not commutative applies between processes).  Rather than try to enumerate and disallow certain actions, I think this is the right solution - the action of the user function on the input parameters is defined; nothing else should be.  An implementation might warn users that the function may be called by multiple threads concurrently (e.g., to use atomic memory operations to count invocations or increment “evil”).<br>
<br>
Bill<br>
<span class="HOEnZb"><font color="#888888"><br>
William Gropp<br>
Director, Parallel Computing Institute<br>
Thomas M. Siebel Chair in Computer Science<br>
Chief Scientist, NCSA<br>
University of Illinois Urbana-Champaign<br>
</font></span><div class="HOEnZb"><div class="h5"><br>
<br>
<br>
<br>
<br>
On Oct 20, 2015, at 1:04 PM, Jeff Hammond <<a href="mailto:jeff.science@gmail.com">jeff.science@gmail.com</a>> wrote:<br>
<br>
> Thanks Jed for clarifying. I agree with your modified example.<br>
><br>
> The fundamental question here remains: can an implementation internally call user-defined reduction operators from multiple threads at the same time?<br>
><br>
> Jeff<br>
><br>
> Sent from my iPhone<br>
><br>
>> On Oct 20, 2015, at 10:50 AM, Jed Brown <<a href="mailto:jedbrown@mcs.anl.gov">jedbrown@mcs.anl.gov</a>> wrote:<br>
>><br>
>> "Balaji, Pavan" <<a href="mailto:balaji@anl.gov">balaji@anl.gov</a>> writes:<br>
>><br>
>>> You can't call MPI functions in there, but you can replace the abort with an exit(1).<br>
>><br>
>> MPI-3.0 p184: "MPI_ABORT may be called inside the function in case of an error."<br>
>><br>
>>> Each user function is called once per process, so "evil" will always be 1, isn't it?  I'm not sure why reentrance is an issue here.<br>
>><br>
>> Jeff said "user code increments evil once between every call to this<br>
>> function so that it should never fail in single-threaded execution".<br>
>><br>
>> A self-contained rendition:<br>
>><br>
>> void User_reduce(void* invec, void* inoutvec, int *len, MPI_Datatype *datatype)<br>
>> {<br>
>> static int evil = 0;<br>
>> double * in = (double*)invec;<br>
>> double * out = (double*)inoutvec;<br>
>> if (*datatype == MPI_DOUBLE && (++evil%2) == 1) {<br>
>>   for (int i=0; i<*len; i++) out[i] = evil*in[i];<br>
>>   evil++;<br>
>> } else {<br>
>>   MPI_Abort(1,MPI_COMM_WORLD);<br>
>> }<br>
>> }<br>
>><br>
>> The results certainly depend on how an implementation segments a buffer<br>
>> and on which process the reduction is called.  Additionally, calling the<br>
>> reduction from multiple threads may cause a non-deterministic abort.<br>
>> _______________________________________________<br>
>> mpi-forum mailing list<br>
>> <a href="mailto:mpi-forum@lists.mpi-forum.org">mpi-forum@lists.mpi-forum.org</a><br>
>> <a href="http://lists.mpi-forum.org/mailman/listinfo.cgi/mpi-forum" rel="noreferrer" target="_blank">http://lists.mpi-forum.org/mailman/listinfo.cgi/mpi-forum</a><br>
> _______________________________________________<br>
> mpi-forum mailing list<br>
> <a href="mailto:mpi-forum@lists.mpi-forum.org">mpi-forum@lists.mpi-forum.org</a><br>
> <a href="http://lists.mpi-forum.org/mailman/listinfo.cgi/mpi-forum" rel="noreferrer" target="_blank">http://lists.mpi-forum.org/mailman/listinfo.cgi/mpi-forum</a><br>
<br>
_______________________________________________<br>
mpi-forum mailing list<br>
<a href="mailto:mpi-forum@lists.mpi-forum.org">mpi-forum@lists.mpi-forum.org</a><br>
<a href="http://lists.mpi-forum.org/mailman/listinfo.cgi/mpi-forum" rel="noreferrer" target="_blank">http://lists.mpi-forum.org/mailman/listinfo.cgi/mpi-forum</a><br>
</div></div></blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature">Jeff Hammond<br><a href="mailto:jeff.science@gmail.com" target="_blank">jeff.science@gmail.com</a><br><a href="http://jeffhammond.github.io/" target="_blank">http://jeffhammond.github.io/</a></div>
</div>