www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Re: Sharing in D

reply Walter Bright <walter nospamm-digitalmars.com> writes:
Steven Schveighoffer Wrote:
 I'm thinking more in the case of functions.  If I have a function foo, and I 
 want to pass my shared data version to it, I need to re-implement foo with 
 the parameters as being shared.  Imagine a function with several parameters, 
 in which you want to pass a combination of shared/unshared.  That's 2^n 
 variations you have to write.

Not necessary, just make them shared. Unshared implicitly converts to shared, so that works. Putting a fence around an unshared read doesn't break anything, etc.
 I think at the very least, for this to be palatable, there needs to be 
 another modifier that unifies shared and unshared.  Similar to how const 
 unifies mutable and invariant.

Shared unifies shared and unshared.
Aug 01 2008
next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Walter Bright" wrote
 Steven Schveighoffer Wrote:
 I'm thinking more in the case of functions.  If I have a function foo, 
 and I
 want to pass my shared data version to it, I need to re-implement foo 
 with
 the parameters as being shared.  Imagine a function with several 
 parameters,
 in which you want to pass a combination of shared/unshared.  That's 2^n
 variations you have to write.

Not necessary, just make them shared. Unshared implicitly converts to shared, so that works. Putting a fence around an unshared read doesn't break anything, etc.

I'm assuming you read my previous example, but I'll rewrite it to demonstrate what I'm trying to show: class sharedObj { private int *_x; synchronized shared int x() {return *_x;} synchronized shared int x(int y) {*_x = y;} synchronized shared void rebind(shared int *y) {_x = y;} } shared sharedObj obj; static this() { obj = new sharedObj; } int *x2; void bar() { obj.x = x2; *x2 = 3; // is this supposed to be guaranteed safe? } Now, Let's say you have thread 1 which calls bar. So now thread 1's x2 and obj._x point to the exact same data, which is both viewed as shared and unshared at the same time. Is this something that should be allowed? Would you not make the assumption that you can do whatever you want with what x2 points to without synchronization because it is unshared? Maybe I don't completely understand what you are intending for shared to mean. I was under the impression that 'unshared' means 'lock free', which cannot be enforcable if you can implicitly cast away the 'lock free' aspect of it. ??? -Steve
Aug 01 2008
next sibling parent Jason House <jason.james.house gmail.com> writes:
Steven Schveighoffer Wrote:

 "Walter Bright" wrote
 Steven Schveighoffer Wrote:
 I'm thinking more in the case of functions.  If I have a function foo, 
 and I
 want to pass my shared data version to it, I need to re-implement foo 
 with
 the parameters as being shared.  Imagine a function with several 
 parameters,
 in which you want to pass a combination of shared/unshared.  That's 2^n
 variations you have to write.

Not necessary, just make them shared. Unshared implicitly converts to shared, so that works. Putting a fence around an unshared read doesn't break anything, etc.

I'm assuming you read my previous example, but I'll rewrite it to demonstrate what I'm trying to show: class sharedObj { private int *_x; synchronized shared int x() {return *_x;} synchronized shared int x(int y) {*_x = y;} synchronized shared void rebind(shared int *y) {_x = y;} } shared sharedObj obj; static this() { obj = new sharedObj; } int *x2; void bar() { obj.x = x2; *x2 = 3; // is this supposed to be guaranteed safe? } Now, Let's say you have thread 1 which calls bar. So now thread 1's x2 and obj._x point to the exact same data, which is both viewed as shared and unshared at the same time. Is this something that should be allowed? Would you not make the assumption that you can do whatever you want with what x2 points to without synchronization because it is unshared? Maybe I don't completely understand what you are intending for shared to mean. I was under the impression that 'unshared' means 'lock free', which cannot be enforcable if you can implicitly cast away the 'lock free' aspect of it. ??? -Steve

Uh oh Steve, you're starting to sound like me! I made the 2^n comment in the context of the const system a while back and now you're looking at how globals might break a transitve data type system... I could have sworn you were the loudest voice against my ideas!
Aug 01 2008
prev sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Steven Schveighoffer wrote:
 Now, Let's say you have thread 1 which calls bar.  So now thread 1's x2 and 
 obj._x point to the exact same data, which is both viewed as shared and 
 unshared at the same time.  Is this something that should be allowed?  Would 
 you not make the assumption that you can do whatever you want with what x2 
 points to without synchronization because it is unshared?  Maybe I don't 
 completely understand what you are intending for shared to mean.

Eh, I think you've got me there. Looks like unshared cannot be implicitly converted to shared.
Aug 01 2008
parent reply Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Walter Bright wrote:
 Steven Schveighoffer wrote:
 Now, Let's say you have thread 1 which calls bar.  So now thread 1's 
 x2 and obj._x point to the exact same data, which is both viewed as 
 shared and unshared at the same time.  Is this something that should 
 be allowed?  Would you not make the assumption that you can do 
 whatever you want with what x2 points to without synchronization 
 because it is unshared?  Maybe I don't completely understand what you 
 are intending for shared to mean.

Eh, I think you've got me there. Looks like unshared cannot be implicitly converted to shared.

Akin to why const cannot be implicitly converted to invariant, no? -- Bruno Medeiros - Software Developer, MSc. in CS/E graduate http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Aug 11 2008
parent reply dsimcha <dsimcha yahoo.com> writes:
One thing that recently popped into my mind about the shared/unshared
discussion:
 What about arrays, etc that are manipulated by multiple threads, but in such a
way that each thread is guaranteed not to touch the same elements as any other
thread, and to never reallocate the array?  This is something I actually do, for
such things as filling in large matrices.  If I understand this proposal
correctly, if the array is unshared, multiple threads can't touch it.  If it is
shared, the compiler will automatically make it synchronized.  In this case, the
synchronization overhead might be large and unnecessary.  If I have each thread
write to separate, unshared data structures and merge them together later, then
I'm adding needless complexity to my code.
Aug 11 2008
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
dsimcha:
  What about arrays, etc that are manipulated by multiple threads, but in such a
 way that each thread is guaranteed not to touch the same elements as any other
 thread, and to never reallocate the array?

If you take a slice of an array [a..b] you don't copy data, so if threads can work on adjacent parts you can slice it in parts that are unshared, and then use the whole usliced block of data... Bye, bearophile
Aug 11 2008
prev sibling parent Sean Kelly <sean invisibleduck.org> writes:
== Quote from dsimcha (dsimcha yahoo.com)'s article
 One thing that recently popped into my mind about the shared/unshared
discussion:
  What about arrays, etc that are manipulated by multiple threads, but in such a
 way that each thread is guaranteed not to touch the same elements as any other
 thread, and to never reallocate the array?  This is something I actually do,
for
 such things as filling in large matrices.  If I understand this proposal
 correctly, if the array is unshared, multiple threads can't touch it.  If it is
 shared, the compiler will automatically make it synchronized.  In this case,
the
 synchronization overhead might be large and unnecessary.  If I have each thread
 write to separate, unshared data structures and merge them together later, then
 I'm adding needless complexity to my code.

For arrays with elements smaller than the bus width or for unaligned arrays there are still word tearing issues, which makes such an approach risky at best. Less importantly, depending on the size and alignment of the array the threads could end up all competing for the same cache line, which would render parallelization of the algorithm largely pointless unless the computation is extremely expensive. It's almost always better to have each thread work on a copy of the data and then merge it later. Sean
Aug 11 2008
prev sibling parent mort <mortm gmail.com> writes:
Walter Bright Wrote:
 Shared unifies shared and unshared.

It seems that you want the semantics for shared to be ``allocated on either the shared heap or the local heap'' and for non-shared to be ``allocated on a thread local heap''. Is that right? If so, then it seems the only safe cast is from non-shared to *const* shared. I think that was what Steven's example was meant to demonstrate (though I had trouble following it).
Aug 01 2008