Boost logo

Boost :

Subject: Re: [boost] Synchronization (RE: [compute] review)
From: Gruenke,Matt (mgruenke_at_[hidden])
Date: 2014-12-30 03:55:53


-----Original Message-----
From: Boost [mailto:boost-bounces_at_[hidden]] On Behalf Of Thomas M
Sent: Tuesday, December 30, 2014 2:49
To: boost_at_[hidden]
Subject: Re: [boost] Synchronization (RE: [compute] review)

>> BTW, for command_queue-level operations, Kyle seems to agree with my proposal
>> to have a sort of guard object that calls event::wait(), upon destruction.
>> I actually wonder if it makes sense to call this a 'guarantee', since it
>> doesn't quite behave like traditional guard objects. He's even accepted my
>> offer to code this up.
>
> If you want to code that functionality up that's more than fine with me.
> I am not happy though with the need to explicitly, i.e. manually, associate
> guards with command-queue operations just for the sake of exception-safety
> (I am referring only to that here). And out of the box I cannot come up with
> a single example when a memory container is fine to die while OpenCL operations
> are still running on it or enqueued to run on it, so that's why I prefer a
> mechanisms which does it always, implicitly (unless maybe the user wants to
> take over it explicitly).
>
> Your proposal looks like:
>
> boost::compute::guard wg(cq.enqueue_write_buffer_async(dv, 0, hv.size(), &hv.front()));
>
> which appears to me quite lengthy and more error-prone (forgetting the
> guard) to get exception safety.

Yes, except I'm now proposing to call it a 'guarantee', since it guarantees that the event will have completed within its lifetime.

> Now assume that an iterator can store its underlying container, isn't it possible
> that the enqueue_write_buffer_async itself places some guard-like structure into
> the container, and when the container's destructor is invoked it calls wait() on
> all of them?

Keep in mind that the guarantee is proposed to be used with command_queue operations, which accept only pointers and buffer objects - not iterators. I think it's not unreasonable if the low level interface requires a bit more care to use, if that makes it more flexible and efficient.

For instance, what if the datastructures on which you're operating are protected from exceptions by some other means (i.e. tied to a scope outside the try block)? Are you still going to force the caller to pay the price of copying the data into a special container? To avoid such overheads, do they then have to drop down to the C interface, and forego all of the other benefits of Boost.Compute?

I agree with Kyle's approach of having a fairly direct and simple interface, at the low level, while trying to make the high-level interface easy & safe. I also agree with you that the high-level interface could be made both safer *and* more efficient, by restricting it to operate only on Boost.Compute containers with some additional facilities (i.e. refcounting in device containers and a guarantee in the host wrapper).

If he'd just buy into that, I think it'd give Boost.Compute all the safety, efficiency, flexibility, and ease of use that anyone needs. There are always going to be tradeoffs. I'd prefer that, rather than the library deciding how to strike the best balance, it give the users a set of good options and let them decide which combination best fits the bill.

Matt

________________________________

This e-mail contains privileged and confidential information intended for the use of the addressees named above. If you are not the intended recipient of this e-mail, you are hereby notified that you must not disseminate, copy or take any action in respect of any information contained in it. If you have received this e-mail in error, please notify the sender immediately by e-mail and immediately destroy this e-mail and its attachments.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk