Replies: 6 comments 1 reply
-
Thanks for reporting your experience of Nevertheless I will consider what is the correct behaviour here - it should be fairly straightforward to allow (i) the ability to wait for Getting the 'i' value on the other hand is not supported by design. Dispatcher performs FIFO scheduling, hence you cannot know beforehand which daemon dispatcher will send a task to. If this is important then use compute profiles to route certain tasks to certain daemons. |
Beta Was this translation helpful? Give feedback.
-
I appreciate your response and agree on the potential mitigations. Thank you. As a point of clarification, what I'm doing with the daemons is an iterative map-reduce pattern; that is, after provisioning them for distributed independent work and after they have completed that work, the daemons require progressive provisioning with more information that can only be ascertained from the reduce phase. It seemed natural to try and use Also, I'm not interested in getting the |
Beta Was this translation helpful? Give feedback.
-
If you are interested in utilisation rate for the daemons then the summary Otherwise, from the point of view of the framework, all daemons (under the same compute profile) are treated the same. It matters not whether one is labelled 1 or 10, hence this information is not made available. If in reality they are not the same, and you need to make use of this fact, then you should make use of compute profiles - this was my earlier point. If just for logging, then that seems to be the responsibility of the logging implementation - for example it seems possible in the case you describe to send everything to one stream rather than 'n' streams - you have the PIDs anyway so you can query the database to get whatever view you want. If there is some other reason I am missing, please feel free to point out. |
Beta Was this translation helpful? Give feedback.
-
Thank you for the reply. I very much appreciate your contributions to the R community. Your perspective on the daemons within the framework you've designed resonates with me. And, as the author, you always have the conch 😄 While I'm not interested in the utilization rate, I still do need to know who turned in homework. Workers are initialized identically, but then may evolve into different states. They receive different data, may run different processes (from their loaded collection), and turn in results that are collated and redistributed. I'm not at liberty to reveal my context and so it's rather difficult to explain. Science requires reproducibility, and that was my motivation. I can most certainly do some great science with your package, but, alas for me, not always easily with my own current logger package 😆 Haha. But I have a workaround and so no lab mice need suffer... until perhaps I hire a new cat to rewrite my old logger(???). I do very much appreciate and use the compute profile via the As I've 'chewed' on my original problem a bit more, I must say that I'm genuinely surprised that no one else noticed that Ironically and perhaps in the context of the original reason I opened the issue, you might begin to appreciate why I was logging what each daemon is doing. The incomplete state was blowing up my science and it took some time to discover why code was working on one run and then not working on another run under what were identical conditions from my vantage point. While I threw in the daemon index question in my posts, it was an honest sidebar question; however, in retrospect, the single best argument for accessing the index [so I can track individual daemon behavior] is this issue about I would have fully expected that someone else would have hit this provisioning situation before me. I appreciate you. Forgive the verbosity and humor. I work by myself too often... |
Beta Was this translation helpful? Give feedback.
-
Given what you're saying, I'm no longer sure it's a good idea to change the behaviour of It is designed to perform setup tasks i.e. right after a call to Other usage is purely incidental, and I'd have to think through the implications thoroughly before I 'bless' them through providing a formal interface (such as the ability to wait). |
Beta Was this translation helpful? Give feedback.
-
I'm nothing if not persistent. Let me try again. The
My HP Elite Dragonfly laptop is not particularly elite (although it is tiny and lightweight), and so your results might vary if you're running this on a Zbook or on an AWS instance. I ran this for 30 seconds and it tripped up a total of 4 times before I interrupted it because this is enough proof:
I consider this buggy. But I cannot argue with what your intentions were when you created the function; however, I can argue that semantics and words matter. If I use the words "setup operation" to describe what a function does (as
And, yes, even if I follow the call to The best I can conclude:
I [might] rest my case... but probably not 😆 |
Beta Was this translation helpful? Give feedback.
-
I'm still thoroughly appreciating this excellent package. Thank you! This is the best thing that has happened to R in several years.
I'm working on an application that needs to process ~850 requests/minute. I've historically used stable persistent clusters (leveraging
parallel
andparallelly
), but I wanted to migrate it to your lovely package since the polling in my previous setup was creating a rather heavy parallel 'tax'. I was noticing some very odd intermittent failures in my set of provisioning functions that ensure all workers are loaded with packages and variables as well as my own parallel logger routines. It seemed at times thateverywhere()
might be failing. I threw some breakpoints in my package and rebuilt and, sure enough, caught what seems to be intermittent points where previous steps of provisioning are not completed even thougheverywhere()
had been called. Rerunning those lines while in the debugger allowed me continue on.On one hand, this makes sense; a
mirai
is an async future. But how does one check on a call toeverywhere()
other than to inspect thesearch()
path,.GlobalEnv
, etc. (depending on what I've done) of each worker since the function has no return value? It took a minute before I resorted to some code violence.Being the gangstR that I am, I decided some good old fashioned torture might get it talk to me. The reprex below will provision 10
daemons()
. Once it makes sure they're connected, I set anode.pid
value in eachdaemon
and then try to retrieve them all by calling an excessive amount ofmirai()
(knowing that there is no reason to expect a uniform set of returns, I can imagine some will be missing from time to time). Because we know those will take time, I add a delay (with exponential backoff). To test whethereverywhere()
also has an effect, too, I place an earlier delay before the set ofmirai
are called. Once allnode.pid
values are recovered from thedaemons
, I reset them and start the provisioning over again and again.Here's a short sample run:
What's interesting is that I notice that commenting out the first delay (after the
everywhere()
) has quite a noticeable effect on the progress (i.e., it gets much worse). This shows up as:I repeated this behavior many times (commenting and uncommenting the first delay). This seems to suggest that I should devise checks after my calls to
everywhere()
to make sure that the provisioning work has completed. Or is there simply a way to block and wait for them to complete as there is withmirai
? Keep in mind, my applications run on Linux but these tests were ran on a very modest Windows laptop; thus, not particularly fast.One other minor/unrelated question: Is there a way to get the
i
value from adaemon
(that shows instatus()
) to know its identity as part of amirai
? It will be handy to know which worker processed my future in a less convoluted way than I've devised locally. Thank youThank you
Beta Was this translation helpful? Give feedback.
All reactions