<br><br><div class="gmail_quote">On Mon, Jul 12, 2010 at 20:43, Brian Granger <span dir="ltr">&lt;<a href="mailto:ellisonbg@gmail.com" target="_blank">ellisonbg@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">


Min,<br>
<div><br>
On Mon, Jul 12, 2010 at 4:10 PM, MinRK &lt;<a href="mailto:benjaminrk@gmail.com" target="_blank">benjaminrk@gmail.com</a>&gt; wrote:<br>
&gt; I&#39;ve been thinking about this, and it seems like we can&#39;t have a responsive<br>
&gt; rich control connection unless it is in another process, like the old<br>
&gt; IPython daemon.<br>
<br>
</div>I am not quite sure I follow what you mean by this.  Can you elaborate?<br></blockquote><div><br></div><div>The main advantage that we were to gain from the out-of-process ipdaemon was the ability to abort/kill (signal) blocking jobs. With 0MQ threads, the only logic we can have in a control/heartbeat thread must be implemented in GIL-free C/C++. That limits what we can do in terms of interacting with the main work thread, as I understand it.</div>


<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div><br>
&gt; Pure heartbeat is easy with a C device, and we may not even<br>
&gt; need a new one. For instance, I added support for the builtin devices of<br>
&gt; zeromq to pyzmq with a few lines, and you can have simple is_alive style<br>
&gt; heartbeat with a FORWARDER device.<br>
<br>
</div>I looked at this and it looks very nice.  I think for basic is_alive<br>
type heartbeats this will work fine.  The only thing to be careful of<br>
is that 0MQ sockets are not thread safe.  Thus, it would be best to<br>
actually create the socket in the thread as well.  But we do want the<br>
flexibility to be able to pass in sockets to the device.  We will have<br>
to think about that issue.<br></blockquote><div> </div><div>I wrote/pushed a basic ThreadsafeDevice, which creates/binds/connects inside the thread&#39;s run method.</div><div>It adds bind_in/out, connect_in/out, and setsockopt_in/out methods which just queue up arguments to be called at the head of the run method. I added a tspong.py in the heartbeat example using it.</div>


<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div><br>
&gt; I pushed a basic example of this (examples/heartbeat) to my pyzmq fork.<br>
&gt; Running a ~3 second numpy.dot action, the heartbeat pings remain responsive<br>
&gt; at &lt;1ms.<br>
<br>
</div>This is great!<br>
<br>
Cheers,<br>
<font color="#888888"><br>
Brian<br>
</font><div><div></div><div>&gt; -MinRK<br>
&gt;<br>
&gt; On Mon, Jul 12, 2010 at 12:51, MinRK &lt;<a href="mailto:benjaminrk@gmail.com" target="_blank">benjaminrk@gmail.com</a>&gt; wrote:<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt; On Mon, Jul 12, 2010 at 09:15, Brian Granger &lt;<a href="mailto:ellisonbg@gmail.com" target="_blank">ellisonbg@gmail.com</a>&gt; wrote:<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; On Fri, Jul 9, 2010 at 3:35 PM, MinRK &lt;<a href="mailto:benjaminrk@gmail.com" target="_blank">benjaminrk@gmail.com</a>&gt; wrote:<br>
&gt;&gt;&gt; &gt; Brian,<br>
&gt;&gt;&gt; &gt; Have you worked on the Heartbeat Device? Does that need to go in 0MQ<br>
&gt;&gt;&gt; &gt; itself,<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; I have not.  Ideally it could go into 0MQ itself.  But, in principle,<br>
&gt;&gt;&gt; we could do it in pyzmq.  We just have to write a nogil pure C<br>
&gt;&gt;&gt; function that uses the low-level C API to do the heartbeat.  Then we<br>
&gt;&gt;&gt; can just run that function in a thread with a &quot;with nogil&quot; block.<br>
&gt;&gt;&gt; Shouldn&#39;t be too bad, given how simple the heartbeat logic is.  The<br>
&gt;&gt;&gt; main thing we will have to think about is how to start/stop the<br>
&gt;&gt;&gt; heartbeat in a clean way.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; &gt; or can it be part of pyzmq?<br>
&gt;&gt;&gt; &gt; I&#39;m trying to work out how to really tell that an engine is down.<br>
&gt;&gt;&gt; &gt; Is the heartbeat to be in a separate process?<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; No, just a separate C/C++ thread that doesn&#39;t hold the GIL.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; &gt; Are we guaranteed that a zmq thread is responsive no matter what an<br>
&gt;&gt;&gt; &gt; engine<br>
&gt;&gt;&gt; &gt; process is doing? If that&#39;s the case, is a moderate timeout on recv<br>
&gt;&gt;&gt; &gt; adequate<br>
&gt;&gt;&gt; &gt; to determine engine failure?<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Yes, I think we can assume this.  The only thing that would take the<br>
&gt;&gt;&gt; 0mq thread down is something semi-fatal like a signal that doesn&#39;t get<br>
&gt;&gt;&gt; handled.  But as long as the 0MQ thread doesn&#39;t have any bugs, it<br>
&gt;&gt;&gt; should simply keep running no matter what the other thread does (OK,<br>
&gt;&gt;&gt; other than segfaulting)<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; &gt; If zmq threads are guaranteed to be responsive, it seems like a simple<br>
&gt;&gt;&gt; &gt; pair<br>
&gt;&gt;&gt; &gt; socket might be good enough, rather than needing a new device. Or even<br>
&gt;&gt;&gt; &gt; through the registration XREP socket.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; That (registration XREP socket) won&#39;t work unless we want to write all<br>
&gt;&gt;&gt; that logic in C.<br>
&gt;&gt;&gt; I don&#39;t know about a PAIR socket because of the need for multiple<br>
&gt;&gt;&gt; clients?<br>
&gt;&gt;<br>
&gt;&gt; I wasn&#39;t thinking of a single PAIR socket, but rather a pair for each<br>
&gt;&gt; engine. We already have a pair for each engine for the queue, but I am not<br>
&gt;&gt; quite seeing the need for a special device beyond a PAIR socket in the<br>
&gt;&gt; heartbeat.<br>
&gt;&gt;<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; &gt; Can we formalize exactly what the heartbeat needs to be?<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; OK, let&#39;s think.  The engine needs to connect, the controller bind.<br>
&gt;&gt;&gt; It would be nice if the controller didn&#39;t need a separate heartbeat<br>
&gt;&gt;&gt; socket for each engine, but I guess we need the ability to track which<br>
&gt;&gt;&gt; specific engine is heartbeating.   Also, there is the question of to<br>
&gt;&gt;&gt; do want to do a reqest/reply or pub/sub style heartbeat.  What do you<br>
&gt;&gt;&gt; think?<br>
&gt;&gt;<br>
&gt;&gt; The way we talked about it, the heartbeat needs to issue commands both<br>
&gt;&gt; ways. While it is used for checking whether an engine remains alive, it is<br>
&gt;&gt; also the avenue for aborting jobs.  If we do have a strict heartbeat, then I<br>
&gt;&gt; think PUB/SUB is a good choice.<br>
&gt;&gt; However, if heartbeat is all it does, then we need a _third_ connection to<br>
&gt;&gt; each engine for control commands. Since messages cannot jump the queue, the<br>
&gt;&gt; engine queue PAIR socket cannot be used for commands, and a PUB/SUB model<br>
&gt;&gt; for heartbeat can _either_ receive commands _or_ have results.<br>
&gt;&gt; control commands:<br>
&gt;&gt; beat (check alive)<br>
&gt;&gt; abort (remove a task from the queue)<br>
&gt;&gt; signal (SIGINT, etc.)<br>
&gt;&gt; exit (engine.kill)<br>
&gt;&gt; reset (clear queue, namespace)<br>
&gt;&gt; more?<br>
&gt;&gt; It&#39;s possible that we could implement these with a PUB on the controller<br>
&gt;&gt; and a SUB on each engine, only interpreting results received via the queue&#39;s<br>
&gt;&gt; PAIR socket. But then every command would be sent to every engine, even<br>
&gt;&gt; though many would only be meant for one (too inefficient/costly?). It would<br>
&gt;&gt; however make the actual heartbeat command very simple as a single send.<br>
&gt;&gt; It does not allow for the engine to initiate queries of the controller,<br>
&gt;&gt; for instance a work stealing implementation. Again, it is possible that this<br>
&gt;&gt; could be implemented via the job queue PAIR socket, but that would only<br>
&gt;&gt; allow for stealing when completely starved for work, since the job queue and<br>
&gt;&gt; communication queue would be the same.<br>
&gt;&gt; There&#39;s also the issue of task dependency.<br>
&gt;&gt; If we are to implement dependency checking as we discussed (depend on<br>
&gt;&gt; taskIDs, and only execute once the task has been completed), the engine<br>
&gt;&gt; needs to be able to query the controller about the tasks depended upon. This<br>
&gt;&gt; makes the controller being the PUB side unworkable.<br>
&gt;&gt; This says to me that we need two-way connections between the engines and<br>
&gt;&gt; the controller. That can either be implemented as multiple connections<br>
&gt;&gt; (PUB/SUB + PAIR or REQ/REP), or simply a PAIR socket for each engine could<br>
&gt;&gt; provide the whole heartbeat/command channel.<br>
&gt;&gt; -MinRK<br>
&gt;&gt;<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Brian<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; &gt; -MinRK<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; --<br>
&gt;&gt;&gt; Brian E. Granger, Ph.D.<br>
&gt;&gt;&gt; Assistant Professor of Physics<br>
&gt;&gt;&gt; Cal Poly State University, San Luis Obispo<br>
&gt;&gt;&gt; <a href="mailto:bgranger@calpoly.edu" target="_blank">bgranger@calpoly.edu</a><br>
&gt;&gt;&gt; <a href="mailto:ellisonbg@gmail.com" target="_blank">ellisonbg@gmail.com</a><br>
&gt;&gt;<br>
&gt;<br>
&gt;<br>
<br>
<br>
<br>
</div></div>--<br>
<div><div></div><div>Brian E. Granger, Ph.D.<br>
Assistant Professor of Physics<br>
Cal Poly State University, San Luis Obispo<br>
<a href="mailto:bgranger@calpoly.edu" target="_blank">bgranger@calpoly.edu</a><br>
<a href="mailto:ellisonbg@gmail.com" target="_blank">ellisonbg@gmail.com</a><br>
</div></div></blockquote></div><br>