<br><font size=2 face="sans-serif">This is how I do it in the GA/ARMCI
reference implementation (see: comm/lib/ga/toolkit/armci/src/x/dcmf/armcix_impl.c)
--- I added some comments for the purpose of this email....</font>
<br>
<br><tt><font size=2>int ARMCIX_Init ()</font></tt>
<br><tt><font size=2>{</font></tt>
<br><tt><font size=2>&nbsp; // This is the only DCMF call that can be invoked
before</font></tt>
<br><tt><font size=2>&nbsp; // DCMF_Messager_initialize(). Interrupt processing
is turned off</font></tt>
<br><tt><font size=2>&nbsp; // in a critical section. Doing this here prevents
the kernel from</font></tt>
<br><tt><font size=2>&nbsp; // firing an interrupt before the local node
has been initialized.</font></tt>
<br><tt><font size=2>&nbsp; DCMF_CriticalSection_enter(0);</font></tt>
<br>
<br><tt><font size=2>&nbsp; DCMF_Messager_initialize ();</font></tt>
<br>
<br><tt><font size=2>&nbsp; ...</font></tt>
<br>
<br><tt><font size=2>&nbsp; DCMF_Configure_t config;</font></tt>
<br><tt><font size=2>&nbsp; memset (&amp;config, 0x00, sizeof(DCMF_Configure_t));</font></tt>
<br><tt><font size=2>&nbsp; config.interrupts = (interrupts==0)?DCMF_INTERRUPTS_OFF:DCMF_INTERRUPTS_ON;</font></tt>
<br><tt><font size=2>&nbsp; </font></tt>
<br><tt><font size=2>&nbsp; // First (input) parameter is the &quot;requested&quot;
configuration, the second</font></tt>
<br><tt><font size=2>&nbsp; // (output) parameter is the actual configuration.
This is important</font></tt>
<br><tt><font size=2>&nbsp; // because multiple independent software libraries
can coexist using</font></tt>
<br><tt><font size=2>&nbsp; // the same dcmf runtime (for example, MPI
and ARMCI). Interrupt mode </font></tt>
<br><tt><font size=2>&nbsp; // in particular can only be enabled, but not
disabled. &nbsp;Because the</font></tt>
<br><tt><font size=2>&nbsp; // application using the independent software
libraries may invoke the</font></tt>
<br><tt><font size=2>&nbsp; // init-type routine for those libraries in
any order it is possible that</font></tt>
<br><tt><font size=2>&nbsp; // the first may request to configure interrupts
on and then second may</font></tt>
<br><tt><font size=2>&nbsp; // request to configure interrupts off. In
this case the second configure</font></tt>
<br><tt><font size=2>&nbsp; // request will not &quot;degrade&quot; the
interrupt level and interrupts will</font></tt>
<br><tt><font size=2>&nbsp; // enabled for the dcmf runtime. &nbsp;Whew!</font></tt>
<br><tt><font size=2>&nbsp; DCMF_Messager_configure (&amp;config, &amp;config);</font></tt>
<br>
<br><tt><font size=2>&nbsp; ...</font></tt>
<br>
<br><tt><font size=2>&nbsp; // Ready to process interrupts now.</font></tt>
<br><tt><font size=2>&nbsp; DCMF_CriticalSection_exit(0);</font></tt>
<br><tt><font size=2>}</font></tt>
<br>
<br>
<br><font size=2 face="sans-serif">I have to point out that, specifically
on BG/P, interrupt mode may not be as useful as you may think. BG/P has
a DMA engine that offloads communication from the cores which allows BG/P
to achieve high overlap of computation and communication. In my experience
with ARMCI - another one-sided API - the remote nodes end up polling &quot;enough&quot;
that progress is always made. In fact, in most ARMCI and GA test cases
the performance is actually lower in interrupt mode.</font>
<br>
<br><font size=2 face="sans-serif">One thing to remember is that a single
call to DCMF_Messager_advance() may invoke many different callbacks (local
completion callbacks, recv notify callbacks, recv done callbacks, etc),
so it's not like you have to call DCMF_Messager_advance() a gajillion times.
Usually you are looping on a variable that will be changed by one of the
callback functions. Other callbacks may be invoked and may be altering
state on other variables, but the loop doesn't exit until the particular
condition is met. Check out this snip (again from the ARMCI reference implementation)
from the file: &nbsp;comm/lib/ga/toolkit/armci/src/x/dcmf/armcix_get.c
:</font>
<br>
<br><tt><font size=2>int ARMCIX_Get(void * src, void * dst, int bytes,
int proc)</font></tt>
<br><tt><font size=2>{</font></tt>
<br><tt><font size=2>&nbsp; DCMF_CriticalSection_enter (0);</font></tt>
<br>
<br><tt><font size=2>&nbsp; volatile unsigned active = 1;</font></tt>
<br><tt><font size=2>&nbsp; DCMF_Callback_t cb_wait = { ARMCIX_DCMF_cb_decrement,
(void *)&amp;active };</font></tt>
<br><tt><font size=2>&nbsp; DCMF_Request_t request;</font></tt>
<br>
<br><tt><font size=2>&nbsp; DCMF_Get ( &amp;__get_protocol,</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&amp;request,</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;cb_wait,</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;DCMF_MATCH_CONSISTENCY,</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;proc,</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;bytes,</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(char
*) dst,</font></tt>
<br><tt><font size=2>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(char
*) src);</font></tt>
<br>
<br><tt><font size=2>&nbsp; while (active) DCMF_Messager_advance ();</font></tt>
<br>
<br><tt><font size=2>&nbsp; DCMF_CriticalSection_exit &nbsp;(0);</font></tt>
<br>
<br><tt><font size=2>&nbsp; return 0;</font></tt>
<br><tt><font size=2>}</font></tt>
<br>
<br><font size=2 face="sans-serif">A couple things to note here ..</font>
<ol>
<li value=1><font size=2 face="sans-serif">the 'volatile' keyword is important
or the compiler may optimize out the while loop.</font>
<li value=2><font size=2 face="sans-serif">the code is wrapped in a critical
section. &nbsp;no point in taking the overhead for an interrupt if you
are actively polling!</font>
<li value=3><font size=2 face="sans-serif">the &quot;cb_wait&quot; callback
just decrements the &quot;active&quot; variable - non-blocking operations
may free the DCMF_Request_t that was used for the operation. Since this
is blocking the DCMF_Request_t was placed on the stack.</font></ol>
<br>
<br>
<br><font size=2 face="sans-serif">Michael Blocksome<br>
Blue Gene Messaging Team Lead<br>
Advanced Systems SW Development<br>
blocksom@us.ibm.com<br>
</font>
<br>
<br><tt><font size=2>rajesh.nishtala@gmail.com wrote on 02/07/2008 03:18:24
PM:<br>
<br>
&gt; Thanks for the answers! They definitely help. In order to reconfigure<br>
&gt; one the messaging layer to use Polling versus interrupts does one
need<br>
&gt; to reinstall/reconfigure the software or is there a way to do it<br>
&gt; within a particular installation. In either case how would one enable<br>
&gt; or disable the 'interrupt mode'. &nbsp;Is this the 'DCMF_Interrupts'
field<br>
&gt; in the DCMF_Configure_t type?<br>
&gt; <br>
&gt; Thanks,<br>
&gt; -rajesh<br>
&gt; <br>
&gt; On Feb 7, 2008 12:12 PM, Michael Blocksome &lt;blocksom@us.ibm.com&gt;
wrote:<br>
&gt; &gt;<br>
&gt; &gt; Rajesh,<br>
&gt; &gt;<br>
&gt; &gt; These are excellent questions! We need to provide better documentation
on<br>
&gt; &gt; how the callback flow works ... baring that, I'll answer your
questions as<br>
&gt; &gt; they come and maybe we can pull together a document after answering
these<br>
&gt; &gt; questions on the mailing list.<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; There are two types of callbacks - think of them as &quot;local
completion&quot; and<br>
&gt; &gt; &quot;remote notification&quot; callbacks.<br>
&gt; &gt;<br>
&gt; &gt; The local completion callbacks are specified not at registration
time, but<br>
&gt; &gt; when an individual operation is started (DCMF_Send(), for example).
This<br>
&gt; &gt; callback is invoked by the dcmf runtime, when the local node
calls the<br>
&gt; &gt; DCMF_Messager_advance() function, after the source buffer has
been<br>
&gt; &gt; completely sent. &nbsp;Once the local completion callback is
invoked all buffers<br>
&gt; &gt; associated with the operation may be deallocated, etc.<br>
&gt; &gt;<br>
&gt; &gt; The callbacks that are registered for DCMF_Send (and DCMF_Control,etc)
with<br>
&gt; &gt; the DCMF_Send_register() function are invoked by the dcmf runtime
on the<br>
&gt; &gt; remote node when that node call the DCMF_Messager_advance() function.<br>
&gt; &gt; Typically all nodes in the system will periodically poll with<br>
&gt; &gt; DCMF_Messager_advance() to make progress, however the BGP messager
can be<br>
&gt; &gt; configured to enable an interupt to be fired when a core receives
a packet.<br>
&gt; &gt; In this interrupt mode active polling is not required - although
you do take<br>
&gt; &gt; a performance hit because of the overhead of processing the interrupts.<br>
&gt; &gt;<br>
&gt; &gt; The remote callbacks for DCMF_Send are invoked before any data
has been<br>
&gt; &gt; written to the remote node. &nbsp;There are two callback types
and each has<br>
&gt; &gt; slightly different use by the application programmer.<br>
&gt; &gt;<br>
&gt; &gt; The DCMF_RecvSendShort (&quot;short&quot;) callbacks are invoked
when the entire<br>
&gt; &gt; message has been received by the remote node into a temporary
location (on<br>
&gt; &gt; BGP this is a single packet of data that has been received by
the DMA into a<br>
&gt; &gt; memory fifo). &nbsp;The application's responsibility is to copy
the data out of<br>
&gt; &gt; the temporary buffer and into the final destination buffer. This
callback<br>
&gt; &gt; type was created specifically to allow the dcmf implementation
to optimize<br>
&gt; &gt; the performance for small messages.<br>
&gt; &gt;<br>
&gt; &gt; The DCMF_RecvSend (&quot;long&quot; or &quot;asynhcronous&quot;)
callbacks are invoked when the<br>
&gt; &gt; control information has been received by the remote node into
a temporary<br>
&gt; &gt; location (on BGP the control information will be contained in
a single<br>
&gt; &gt; packet). &nbsp;The application's responsibility is to allocate
memory<br>
&gt; &gt; (DCMF_Request_t) for the dcmf runtime to use to receive the rest
of the<br>
&gt; &gt; data, as well as specify the destination buffer and length and
a<br>
&gt; &gt; (&quot;recv_done&quot;) callback. This &quot;recv_done&quot;
callback is invoked by the dcmf<br>
&gt; &gt; runtime when the data has been completely received and written
to the<br>
&gt; &gt; destination buffer. &nbsp;Typically applications will free/deallocate
the<br>
&gt; &gt; DCMF_Request_t memory that was allocated previously.<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; DCMF_Put and memory regions (i.e., registration, pinning)<br>
&gt; &gt;<br>
&gt; &gt; The DCMF_Put in the library is just stubbed in as we didn't have
a need for<br>
&gt; &gt; it in release 1 of the BG/P software. &nbsp;However, we are actively
working on<br>
&gt; &gt; adding the DCMF_Put() into the API which will also require a
memory region<br>
&gt; &gt; API. The existing DCMF_Get API will be updated to use these new
memory<br>
&gt; &gt; regions objects. &nbsp;Perhaps we should go into more detail
on the memory region<br>
&gt; &gt; API in a separate email.<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; I hope this helps!<br>
&gt; &gt;<br>
&gt; &gt; Michael Blocksome<br>
&gt; &gt; &nbsp;Blue Gene Messaging Team Lead<br>
&gt; &gt; &nbsp;Advanced Systems SW Development<br>
&gt; &gt; &nbsp;blocksom@us.ibm.com<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; &nbsp;&quot;Rajesh Nishtala&quot; &lt;rajeshn@eecs.berkeley.edu&gt;<br>
&gt; &gt; Sent by: dcmf-bounces@lists.anl-external.org<br>
&gt; &gt;<br>
&gt; &gt; 02/07/2008 12:01 PM<br>
&gt; &gt;<br>
&gt; &gt; To dcmf@lists.anl-external.org<br>
&gt; &gt;<br>
&gt; &gt; cc upc-devel@lbl.gov<br>
&gt; &gt;<br>
&gt; &gt; Subject [dcmf] Question about DCMF Library from a new user<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; Hi,<br>
&gt; &gt; &nbsp;I am porting GASNet, our portable runtime layer for the
Berkeley UPC<br>
&gt; &gt; &nbsp;compiler, to the BlueGene/P and i'm using DCMF as the lower
level<br>
&gt; &gt; &nbsp;messaging layer. I have some high level questions regarding
the<br>
&gt; &gt; &nbsp;library that will influence the design of our BlueGene/P
port. The<br>
&gt; &gt; &nbsp;main difference between our library and MPI is that we
focus on<br>
&gt; &gt; &nbsp;one-sided communication so my main questions are regarding
these<br>
&gt; &gt; &nbsp;issues.<br>
&gt; &gt;<br>
&gt; &gt; &nbsp;+ When does the callback that gets registered with DCMF_Send()
get<br>
&gt; &gt; &nbsp;called? Does it get called after the data has been committed
to the<br>
&gt; &gt; &nbsp;memory on the remote node or does it simply imply that
the data buffer<br>
&gt; &gt; &nbsp;is safe to reuse on the local node?<br>
&gt; &gt;<br>
&gt; &gt; &nbsp;+ I notice that when I do an nm on the dcmf libraries there
is<br>
&gt; &gt; &nbsp;DCMF_Put() function, however when i waded through the code
a little<br>
&gt; &gt; &nbsp;bit more I noticed that the function simply called an abort
which to<br>
&gt; &gt; &nbsp;me implies that it is not implemented. Is this why it doesn't
show up<br>
&gt; &gt; &nbsp;in the dcmf.h header files?<br>
&gt; &gt;<br>
&gt; &gt; &nbsp;+ I have heard that the BlueGene/P supports RDMA operations.
Are there<br>
&gt; &gt; &nbsp;any special considerations for managing the memory registration
(i.e.<br>
&gt; &gt; &nbsp;memory pinning) to enable these operations or is this done<br>
&gt; &gt; &nbsp;automatically under the covers?<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; &nbsp;Thanks in advance for any help!<br>
&gt; &gt;<br>
&gt; &gt; &nbsp;Sincerely,<br>
&gt; &gt; &nbsp;Rajesh Nishtala<br>
&gt; &gt; &nbsp;_______________________________________________<br>
&gt; &gt; &nbsp;dcmf mailing list<br>
&gt; &gt; &nbsp;dcmf@lists.anl-external.org<br>
&gt; &gt; &nbsp;http://lists.anl-external.org/cgi-bin/mailman/listinfo/dcmf<br>
&gt; &gt; &nbsp;http://dcmf.anl-external.org/wiki<br>
&gt; &gt;<br>
&gt; &gt;<br>
</font></tt>