Struggling to implement parallel foreach...
Timon Gehr
timon.gehr at gmx.ch
Tue Jun 18 01:53:54 UTC 2019
On 18.06.19 02:30, Manu wrote:
> On Tue, Jun 18, 2019 at 10:00 AM Timon Gehr via Digitalmars-d
> <digitalmars-d at puremagic.com> wrote:
>>
>> ...
>>
>> threadsafe(unshared) needs to have read/write access removed
>> (completely, UB if you access with casts).
>>
>> shared needs to have unsynchronized read/write access removed. There are
>> multiple ways to go about this:
>>
>> 1. shared data cannot be accessed directly, all accesses need to go
>> through special druntime functions.
>>
>> 2. direct accesses to shared data are atomic/sequentially consistent,
>> other kinds of consistency guarantees are supported with special
>> druntime functions.
>>
>> 3. direct accesses to shared data have low consistency guarantees (some
>> sort of lowest-common-denominator of what's provided by weak memory
>> models), if you want more consistency guarantees, you need to use
>> special druntime functions.
>
> 1: Simplest and least opinionated approach.
> 2: Is only possible for exactly one type; `int`, and breaks down if
> there are 2 int's. Anything else is #1 anyway. Just let the user call
> atomicInc() for clarity rather than pretending `++` is safe.
> 3: What does that mean in practise? Any implementation where you can
> access data members directly is no better than our naming conventions
> in C++.
>
>> Why is 1 better than 2 or 3? (I think Walter is actually leaning towards
>> 2 at the moment.)
>
> Start with 1, reach for 2 as an expansion. 1 is subset of 2.
> ...
This makes sense. 1. is clearly the way to go. I think your "3:" is
actually the strongest point. If some atomic accesses are transparent,
it is way too easy to accidentally treat a `shared` variable as if it
was unshared.
>>>> ...
>>>> I think it's related to why Manu is so confused.
>>>
>>> I don't think I'm as confused as you'd like to think.
>>
>> I'd have liked to think you are exactly as confused as someone who
>> argues that useful closure capturing behavior is a blocker for a
>> parallel `foreach` implementation, but you have been slowly backing down
>> on that claim, so it is indeed likely that you are less confused now
>> than you seemed to be when I wrote that post. :)
>
> I haven't backed down.
You said something to the effect of "fix it like you want".
If you maintain that qualified capturing is a blocker for parallel
foreach (with opApply taking a delegate with a `shared` context). I'll
maintain that you are confused. Qualified capturing is not a blocker for
such a parallel foreach in any way, shape or form.
> Large elements of my suggestion have been
> misunderstood (or were omitted from my suggestion).
> I know I can't convince you, and I don't want to try. You have your
> own ideas, I'll see where it goes.
> ...
Maybe you can show a full code example where you are capturing an
unqualified `int` (then typed as `shared(int)`, because the qualifier is
applied to the entire stack frame) in the body of an foreach with an
opApply that takes a `shared` delegate, that would actually compile and
run with the semantics you have in mind.
If you do that, one of the following things will happen:
1. I extend your example such that it leads to shared/unshared aliasing.
2. I accept that your example can be made to compile, but I will explain
that it can be made to compile just as easily with qualified capturing.
3. I concede the point and apologize.
>>> I understand I'm proposing to obliterate a thing. It's a complex and surprising thing,
>>> and as far as I can tell, it's useless, and only a point of friction
>>> and bugs. Can you show how it's useful?
>>> ...
>>
>> ...
>
> I don't know what you're saying here.
> ...
My second guess for the "obliterated thing" you were referring to is
qualified capturing (the first guess was the existing `shared` qualifier).
If I guessed correctly this time, you were not making yourself very
clear. This is not complex or surprising at all!
>> I don't think he is on board with the redefinition of `shared` to
>> `threadsafe`. For `threadsafe`, default access on unshared data must
>> obviously be disallowed. For `shared` this is less obvious if you don't
>> already assume it has the new meaning.
>
> We can drop this 'threadsafe' thing you have going on. I yielded on
> that discussion months ago, we need shared to not be broken first.
>
That's good to know. I considered it as an alternative because Nicholas
brought it up and you referred to shared being "like const".
More information about the Digitalmars-d
mailing list