chapel-lang / chapel

a Productive Parallel Programming Language
https://chapel-lang.org
Other
1.78k stars 418 forks source link

ZMQ - Adding a timeout argument #13002

Open LouisJenkinsCS opened 5 years ago

LouisJenkinsCS commented 5 years ago

I'm interested in developing a quick and easy Channel abstraction in Chapel that will make use of ZMQ for message passing between tasks, whether local or remote. This is related to my issue on creating a 'Golang channel' abstraction in Chapel: https://github.com/chapel-lang/chapel/issues/12660. However before I can use it, non-blocking behavior is a must, and. I was looking at how to quickly and easily apply this in the current ZMQ module.

https://github.com/chapel-lang/chapel/blob/a6fb91fe4395992e6fae6392b1d824ea35ed708e/modules/packages/ZMQ.chpl#L878-L885

Side-Note: ZMQ module is highlighting some potential issue in textmate bundle w.r.t syntax highlighting

I'm wonder, if we add an optional timeout argument, and then polled based on that timeout to determine whether or not we return early, would that suffice? As well, a sendnb can be implemented as such...

// '-1' timeout means no timeout.
proc send(data:?T, timeout:real = -1, TimeUnits.milliseconds) throws {}
// Non-blocking send just sets timeout to 0ms, meaning it only tries once.
proc sendnb(data:?T) throws {
   send(data, 0);
}

Am I missing something here?

lydia-duncan commented 5 years ago

I believe the typically strategy in ZMQ is to set the timeout on sends/receives on a per socket basis. It looks like there's a ZMQ_RCVTIMEO and ZMQ_SNDTIMEO constant for the C implementation to use in setsockopt, so we'd probably want to implement a setRecvTimeout/setSendTimeout method on sockets. If you really were looking for a per-send/recv timeout, I'd have to look deeper into if ZMQ is really intended for that sort of thing or if other languages' ZMQ implementations try to do that.

I believe sends are already non-blocking, though. I've also seen sends occur when the partner socket hasn't been set up yet and the later recv still obtains the value. Is this a concern because you've had difficulties? Or for a particular socket pair strategy? Or just anticipating?

LouisJenkinsCS commented 5 years ago

I believe sends are already non-blocking, though. I've also seen sends occur when the partner socket hasn't been set up yet and the later recv still obtains the value. Is this a concern because you've had difficulties? Or for a particular socket pair strategy? Or just anticipating?

Mostly anticipating. However the current implementation (and documentation) does not seem to allow specifying any timeout or provide a way to make it non-blocking yet.

I believe the typically strategy in ZMQ is to set the timeout on sends/receives on a per socket basis.

This sounds reasonable. I suppose that if I can set ZMQ_SNDTIMEO or ZMQ_RCVTIMEO to 0 and just poll in my own abstraction, that would suffice. However...

"Internally, the ZMQ module uses non-blocking calls to zmq_send() and zmq_recv() to transfer data, and yields to the tasking layer via chpl_task_yield() when the call would otherwise block."

If ZMQ module internally makes all ZMQ calls non-blocking... how does this work w.r.t the send and receive timeout set by the user?

lydia-duncan commented 5 years ago

Oh, that's fair.

If ZMQ module internally makes all ZMQ calls non-blocking... how does this work w.r.t the send and receive timeout set by the user?

Well, since we didn't allow the timeout to be set before, it didn't do anything about it :) It's definitely something to think about when implementing