Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.programming.threads > #269 > unrolled thread
| Started by | Masakuni Oishi <yamasa@bsdhouse.org> |
|---|---|
| First post | 2011-06-13 09:40 -0700 |
| Last post | 2011-06-15 02:06 -0700 |
| Articles | 20 on this page of 84 — 6 participants |
Back to article view | Back to comp.programming.threads
questions about memory_order_seq_cst fence Masakuni Oishi <yamasa@bsdhouse.org> - 2011-06-13 09:40 -0700
Re: questions about memory_order_seq_cst fence Edek <edek.pienkowski@gmail.com> - 2011-06-13 22:39 +0200
Re: questions about memory_order_seq_cst fence Masakuni Oishi <yamasa@bsdhouse.org> - 2011-06-14 08:27 -0700
Re: questions about memory_order_seq_cst fence Edek <edek.pienkowski@gmail.com> - 2011-06-16 00:21 +0200
Re: questions about memory_order_seq_cst fence Joshua Maurice <joshuamaurice@gmail.com> - 2011-06-15 15:48 -0700
Re: questions about memory_order_seq_cst fence Masakuni Oishi <yamasa@bsdhouse.org> - 2011-06-16 05:03 -0700
Re: questions about memory_order_seq_cst fence Anthony Williams <anthony.ajw@gmail.com> - 2011-06-16 08:35 +0100
Re: questions about memory_order_seq_cst fence Alexander Terekhov <terekhov@web.de> - 2011-06-16 12:05 +0200
Re: questions about memory_order_seq_cst fence Anthony Williams <anthony.ajw@gmail.com> - 2011-06-16 11:19 +0100
Re: questions about memory_order_seq_cst fence Alexander Terekhov <terekhov@web.de> - 2011-06-16 13:57 +0200
Re: questions about memory_order_seq_cst fence Anthony Williams <anthony.ajw@gmail.com> - 2011-06-16 13:51 +0100
Re: questions about memory_order_seq_cst fence Alexander Terekhov <terekhov@web.de> - 2011-06-16 16:53 +0200
Re: questions about memory_order_seq_cst fence Anthony Williams <anthony.ajw@gmail.com> - 2011-06-16 16:17 +0100
Re: questions about memory_order_seq_cst fence Alexander Terekhov <terekhov@web.de> - 2011-06-16 17:37 +0200
Re: questions about memory_order_seq_cst fence "Chris M. Thomasson" <cristom@charter.net> - 2011-06-16 08:47 -0700
Re: questions about memory_order_seq_cst fence Anthony Williams <anthony.ajw@gmail.com> - 2011-06-16 16:54 +0100
Re: questions about memory_order_seq_cst fence "Chris M. Thomasson" <cristom@charter.net> - 2011-06-16 09:01 -0700
Re: questions about memory_order_seq_cst fence Anthony Williams <anthony.ajw@gmail.com> - 2011-06-16 17:07 +0100
Re: questions about memory_order_seq_cst fence "Chris M. Thomasson" <cristom@charter.net> - 2011-06-16 13:59 -0700
Re: questions about memory_order_seq_cst fence Joshua Maurice <joshuamaurice@gmail.com> - 2011-06-16 14:32 -0700
Re: questions about memory_order_seq_cst fence Anthony Williams <anthony.ajw@gmail.com> - 2011-06-17 08:03 +0100
Re: questions about memory_order_seq_cst fence Alexander Terekhov <terekhov@web.de> - 2011-06-17 16:19 +0200
Re: questions about memory_order_seq_cst fence Anthony Williams <anthony.ajw@gmail.com> - 2011-06-17 15:40 +0100
Re: questions about memory_order_seq_cst fence Alexander Terekhov <terekhov@web.de> - 2011-06-30 14:26 +0200
Re: questions about memory_order_seq_cst fence "Chris M. Thomasson" <cristom@charter.net> - 2011-06-17 15:24 -0700
Re: questions about memory_order_seq_cst fence Joshua Maurice <joshuamaurice@gmail.com> - 2011-06-18 03:49 -0700
Re: questions about memory_order_seq_cst fence "Chris M. Thomasson" <cristom@charter.net> - 2011-06-18 14:40 -0700
Re: questions about memory_order_seq_cst fence Joshua Maurice <joshuamaurice@gmail.com> - 2011-06-18 15:46 -0700
Re: questions about memory_order_seq_cst fence "Chris M. Thomasson" <cristom@charter.net> - 2011-06-18 20:27 -0700
Re: questions about memory_order_seq_cst fence Joshua Maurice <joshuamaurice@gmail.com> - 2011-06-18 21:31 -0700
Re: questions about memory_order_seq_cst fence Joshua Maurice <joshuamaurice@gmail.com> - 2011-06-18 21:37 -0700
Re: questions about memory_order_seq_cst fence "Chris M. Thomasson" <cristom@charter.net> - 2011-06-20 15:45 -0700
Re: questions about memory_order_seq_cst fence Joshua Maurice <joshuamaurice@gmail.com> - 2011-06-20 20:05 -0700
Re: questions about memory_order_seq_cst fence Alexander Terekhov <terekhov@web.de> - 2011-06-18 14:06 +0200
Re: questions about memory_order_seq_cst fence Alexander Terekhov <terekhov@web.de> - 2011-06-16 18:32 +0200
Re: questions about memory_order_seq_cst fence "Chris M. Thomasson" <cristom@charter.net> - 2011-06-16 15:42 -0700
Re: questions about memory_order_seq_cst fence Edek <edek.pienkowski@gmail.com> - 2011-07-10 19:47 +0200
Re: questions about memory_order_seq_cst fence "Chris M. Thomasson" <cristom@charter.net> - 2011-06-16 08:51 -0700
Re: questions about memory_order_seq_cst fence Anthony Williams <anthony.ajw@gmail.com> - 2011-06-16 17:23 +0100
Re: questions about memory_order_seq_cst fence Alexander Terekhov <terekhov@web.de> - 2011-06-16 18:49 +0200
Re: questions about memory_order_seq_cst fence "Chris M. Thomasson" <cristom@charter.net> - 2011-06-16 08:51 -0700
Re: questions about memory_order_seq_cst fence Alexander Terekhov <terekhov@web.de> - 2011-06-16 17:25 +0200
Re: questions about memory_order_seq_cst fence Anthony Williams <anthony.ajw@gmail.com> - 2011-06-16 16:56 +0100
Re: questions about memory_order_seq_cst fence Alexander Terekhov <terekhov@web.de> - 2011-06-18 14:28 +0200
Re: questions about memory_order_seq_cst fence Anthony Williams <anthony.ajw@gmail.com> - 2011-06-20 09:54 +0100
Re: questions about memory_order_seq_cst fence Alexander Terekhov <terekhov@web.de> - 2011-06-20 15:39 +0200
Re: questions about memory_order_seq_cst fence Alexander Terekhov <terekhov@web.de> - 2011-06-22 13:24 +0200
Re: questions about memory_order_seq_cst fence Edek <edek.pienkowski@gmail.com> - 2011-06-16 14:39 +0200
Re: questions about memory_order_seq_cst fence Anthony Williams <anthony.ajw@gmail.com> - 2011-06-16 13:55 +0100
Re: questions about memory_order_seq_cst fence Alexander Terekhov <terekhov@web.de> - 2011-06-16 12:03 +0200
Re: questions about memory_order_seq_cst fence Edek <edek.pienkowski@gmail.com> - 2011-07-10 19:10 +0200
Re: questions about memory_order_seq_cst fence Joshua Maurice <joshuamaurice@gmail.com> - 2011-06-13 16:00 -0700
Re: questions about memory_order_seq_cst fence Joshua Maurice <joshuamaurice@gmail.com> - 2011-06-13 23:31 -0700
Re: questions about memory_order_seq_cst fence Masakuni Oishi <yamasa@bsdhouse.org> - 2011-06-14 08:32 -0700
Re: questions about memory_order_seq_cst fence Anthony Williams <anthony.ajw@gmail.com> - 2011-06-14 23:05 +0100
Re: questions about memory_order_seq_cst fence Joshua Maurice <joshuamaurice@gmail.com> - 2011-06-14 16:44 -0700
Re: questions about memory_order_seq_cst fence Anthony Williams <anthony.ajw@gmail.com> - 2011-06-15 08:34 +0100
Re: questions about memory_order_seq_cst fence Masakuni Oishi <yamasa@bsdhouse.org> - 2011-06-15 02:11 -0700
Re: questions about memory_order_seq_cst fence Joshua Maurice <joshuamaurice@gmail.com> - 2011-06-15 15:58 -0700
Re: questions about memory_order_seq_cst fence Anthony Williams <anthony.ajw@gmail.com> - 2011-06-16 08:26 +0100
Re: questions about memory_order_seq_cst fence Masakuni Oishi <yamasa@bsdhouse.org> - 2011-06-16 05:05 -0700
Re: questions about memory_order_seq_cst fence Anthony Williams <anthony.ajw@gmail.com> - 2011-06-16 13:11 +0100
Re: questions about memory_order_seq_cst fence Alexander Terekhov <terekhov@web.de> - 2011-06-18 15:42 +0200
Re: questions about memory_order_seq_cst fence Anthony Williams <anthony.ajw@gmail.com> - 2011-06-20 09:27 +0100
Re: questions about memory_order_seq_cst fence Alexander Terekhov <terekhov@web.de> - 2011-06-20 15:30 +0200
Re: questions about memory_order_seq_cst fence Anthony Williams <anthony.ajw@gmail.com> - 2011-06-20 15:00 +0100
Re: questions about memory_order_seq_cst fence Alexander Terekhov <terekhov@web.de> - 2011-06-21 14:54 +0200
Re: questions about memory_order_seq_cst fence Alexander Terekhov <terekhov@web.de> - 2011-06-21 18:37 +0200
Re: questions about memory_order_seq_cst fence Alexander Terekhov <terekhov@web.de> - 2011-06-21 15:59 +0200
Re: questions about memory_order_seq_cst fence Anthony Williams <anthony.ajw@gmail.com> - 2011-06-22 09:01 -0700
Re: questions about memory_order_seq_cst fence Anthony Williams <anthony.ajw@gmail.com> - 2011-06-20 15:41 +0100
Re: questions about memory_order_seq_cst fence Masakuni Oishi <yamasa@bsdhouse.org> - 2011-06-20 23:24 -0700
Re: questions about memory_order_seq_cst fence Masakuni Oishi <yamasa@bsdhouse.org> - 2011-06-22 10:46 -0700
Re: questions about memory_order_seq_cst fence Masakuni Oishi <yamasa@bsdhouse.org> - 2011-06-22 11:19 -0700
Re: questions about memory_order_seq_cst fence Masakuni Oishi <yamasa@bsdhouse.org> - 2011-06-22 11:57 -0700
Re: questions about memory_order_seq_cst fence Alexander Terekhov <terekhov@web.de> - 2011-06-27 14:05 +0200
Re: questions about memory_order_seq_cst fence Joshua Maurice <joshuamaurice@gmail.com> - 2011-06-29 16:14 -0700
Re: questions about memory_order_seq_cst fence Anthony Williams <anthony.ajw@gmail.com> - 2011-06-24 01:42 -0700
Re: questions about memory_order_seq_cst fence Alexander Terekhov <terekhov@web.de> - 2011-06-27 13:24 +0200
Re: questions about memory_order_seq_cst fence Anthony Williams <anthony.ajw@gmail.com> - 2011-07-01 02:25 -0700
Re: questions about memory_order_seq_cst fence Alexander Terekhov <terekhov@web.de> - 2011-07-01 12:48 +0200
Re: questions about memory_order_seq_cst fence Masakuni Oishi <yamasa@bsdhouse.org> - 2011-06-15 01:53 -0700
Re: questions about memory_order_seq_cst fence Joshua Maurice <joshuamaurice@gmail.com> - 2011-06-15 02:57 -0700
Re: questions about memory_order_seq_cst fence "Chris M. Thomasson" <cristom@charter.net> - 2011-06-15 02:06 -0700
Page 4 of 5 — ← Prev page 1 2 3 [4] 5 Next page →
| From | Masakuni Oishi <yamasa@bsdhouse.org> |
|---|---|
| Date | 2011-06-16 05:05 -0700 |
| Message-ID | <4358686f-7bfb-480e-ae71-a8ce57566ab0@l14g2000pro.googlegroups.com> |
| In reply to | #287 |
Anthony Williams <anthony....@gmail.com> wrote: > Anthony Williams <anthony....@gmail.com> writes: > > Joshua Maurice <joshuamaur...@gmail.com> writes: > > >>> 29.3p7 of N3290 says: > > >>> "For atomic operations A and B on an atomic object M, if there are > >>> memory_order_seq_cst fences X and Y such that A is sequenced before X, Y > >>> is sequenced before B, and X precedes Y in S, then B occurs later than A > >>> in the modification order of M." > > >> I think it's meant to read: > >> [] > >> For atomic **write (and atomic read-modify-write operations)** A and B > >> on an atomic object M, if there are memory_order_seq_cst fences X and > >> Y such that A is sequenced before X, Y is sequenced before B, and X > >> precedes Y in S, then B occurs later than A in the modification order > >> of M. > >> [/] > > > When we drafted this words, I think we meant "operation". It is the > > reference to "modification order" that is the typo. What is meant is > > that if A is a write and B is a read then B must read the value written > > by A, or something later in the modification order; if A is a write and > > B is a write then B must be later than A in the MO; if A is a read and B > > is a write then A must read a value prior to B in the MO, and if A is a > > read and B is a read then B must read the same value as A or a value > > later in the MO. > > After rereading this section of the standard several times, I'm no > > longer sure. I'll have to check my notes. > > I've checked my notes. My recollection was wrong. > > We *discussed* requiring seq_cst fences to order loads like this, but > decided to explicitly limit the orderings to writes. The approved > wording said "where A and B modify M", but this somehow got lost. > > In particular, it was felt that requiring this would add complexity to > the IA-64 implementation of fences, and potentially require that relaxed > operations on that architecture would also have to be more expensive, > thus requiring people to pay for features they didn't need. Interesting. If so, for the code 1 in my first post, is the outcome r1 == 0 && r2 == 1 && r3 == 0 possible on IA-64? In fact, I encountered this problem when I was implementing a variant of work-stealing deque (*). And I'm dissatisfied with the result that the code 2 works well but the code 1 doesn't. (*) http://portal.acm.org/citation.cfm?doid=277651.277678 -- masakuni
[toc] | [prev] | [next] | [standalone]
| From | Anthony Williams <anthony.ajw@gmail.com> |
|---|---|
| Date | 2011-06-16 13:11 +0100 |
| Message-ID | <871uyuasc0.fsf@justsoftwaresolutions.co.uk> |
| In reply to | #293 |
Masakuni Oishi <yamasa@bsdhouse.org> writes: > If so, for the code 1 in my first post, is the outcome > r1 == 0 && r2 == 1 && r3 == 0 possible on IA-64? I believe so. Anthony -- Author of C++ Concurrency in Action http://www.stdthread.co.uk/book/ just::thread C++0x thread library http://www.stdthread.co.uk Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk 15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976
[toc] | [prev] | [next] | [standalone]
| From | Alexander Terekhov <terekhov@web.de> |
|---|---|
| Date | 2011-06-18 15:42 +0200 |
| Message-ID | <4DFCAB39.35CDACC8@web.de> |
| In reply to | #295 |
Anthony Williams wrote: > > Masakuni Oishi <yamasa@bsdhouse.org> writes: > > > If so, for the code 1 in my first post, is the outcome > > r1 == 0 && r2 == 1 && r3 == 0 possible on IA-64? > > I believe so. Perhaps this is relevant: http://download.intel.com/design/itanium/downloads/25142901.pdf See 3.3.7.1 Total ordering of WB Releases. (remote write atomicity) regards, alexander.
[toc] | [prev] | [next] | [standalone]
| From | Anthony Williams <anthony.ajw@gmail.com> |
|---|---|
| Date | 2011-06-20 09:27 +0100 |
| Message-ID | <87oc1ssyaq.fsf@justsoftwaresolutions.co.uk> |
| In reply to | #324 |
Alexander Terekhov <terekhov@web.de> writes: > Anthony Williams wrote: >> >> Masakuni Oishi <yamasa@bsdhouse.org> writes: >> >> > If so, for the code 1 in my first post, is the outcome >> > r1 == 0 && r2 == 1 && r3 == 0 possible on IA-64? >> >> I believe so. > > Perhaps this is relevant: > > http://download.intel.com/design/itanium/downloads/25142901.pdf > > See 3.3.7.1 Total ordering of WB Releases. > > (remote write atomicity) Maybe I'm wrong; I am not an expert on IA-64 semantics. Anthony -- Author of C++ Concurrency in Action http://www.stdthread.co.uk/book/ just::thread C++0x thread library http://www.stdthread.co.uk Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk 15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976
[toc] | [prev] | [next] | [standalone]
| From | Alexander Terekhov <terekhov@web.de> |
|---|---|
| Date | 2011-06-20 15:30 +0200 |
| Message-ID | <4DFF4B71.20A46979@web.de> |
| In reply to | #331 |
Anthony Williams wrote: > > Alexander Terekhov <terekhov@web.de> writes: > > > Anthony Williams wrote: > >> > >> Masakuni Oishi <yamasa@bsdhouse.org> writes: > >> > >> > If so, for the code 1 in my first post, is the outcome > >> > r1 == 0 && r2 == 1 && r3 == 0 possible on IA-64? > >> > >> I believe so. > > > > Perhaps this is relevant: > > > > http://download.intel.com/design/itanium/downloads/25142901.pdf > > > > See 3.3.7.1 Total ordering of WB Releases. > > > > (remote write atomicity) > > Maybe I'm wrong; I am not an expert on IA-64 semantics. Suppose that I can program in terms of C++MM's acquire/release. The platform is x86. How am I supposed to ensure remote write atomicity ala IA-64 releases for a particular store (relevant loads) using C++MM and NOT pessimizing everything to seq_cst? The next question is regarding store-load fencing for particular release-store and subsequent acquire-load. If both can not be done easily under C++MM then it is pretty useless to me. regards, alexander.
[toc] | [prev] | [next] | [standalone]
| From | Anthony Williams <anthony.ajw@gmail.com> |
|---|---|
| Date | 2011-06-20 15:00 +0100 |
| Message-ID | <871uyosiuw.fsf@justsoftwaresolutions.co.uk> |
| In reply to | #333 |
Alexander Terekhov <terekhov@web.de> writes: > Anthony Williams wrote: >> >> Alexander Terekhov <terekhov@web.de> writes: >> >> > Anthony Williams wrote: >> >> >> >> Masakuni Oishi <yamasa@bsdhouse.org> writes: >> >> >> >> > If so, for the code 1 in my first post, is the outcome >> >> > r1 == 0 && r2 == 1 && r3 == 0 possible on IA-64? >> >> >> >> I believe so. >> > >> > Perhaps this is relevant: >> > >> > http://download.intel.com/design/itanium/downloads/25142901.pdf >> > >> > See 3.3.7.1 Total ordering of WB Releases. >> > >> > (remote write atomicity) >> >> Maybe I'm wrong; I am not an expert on IA-64 semantics. > > Suppose that I can program in terms of C++MM's acquire/release. The > platform is x86. > > How am I supposed to ensure remote write atomicity ala IA-64 releases > for a particular store (relevant loads) using C++MM and NOT pessimizing > everything to seq_cst? In the general case, you can't. Acquire/release is essentially pairwise synchronization in the C++0x MM; if you need a total order then you must use seq_cst. However, in particular cases then you can order particular subsets. If you have an example of code that you would like to work then I can see if I can think of a way to make it work without using seq_cst everywhere. > The next question is regarding store-load fencing for particular > release-store and subsequent acquire-load. One issue here is that the terminology and effects of SPARC membar constraints do not map cleanly onto C++0x ordering constraints. SPARC membar constraints relate instruction order to global visibility order. C++0x ordering constraints are transitive pairwise constraints between processors, apart from seq_cst which is a global ordering on seq_cst operations. Consequently there is not always a simple 1-1 translation between the two, but you should be able to achieve the same effects. If there are cases where you can't, then I am interested to understand the issues, and see how the C++ MM could be extended to handle the new cases. Anthony -- Author of C++ Concurrency in Action http://www.stdthread.co.uk/book/ just::thread C++0x thread library http://www.stdthread.co.uk Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk 15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976
[toc] | [prev] | [next] | [standalone]
| From | Alexander Terekhov <terekhov@web.de> |
|---|---|
| Date | 2011-06-21 14:54 +0200 |
| Message-ID | <4E009468.4B9FF511@web.de> |
| In reply to | #335 |
Anthony Williams wrote: [...] > > Suppose that I can program in terms of C++MM's acquire/release. The > > platform is x86. > > > > How am I supposed to ensure remote write atomicity ala IA-64 releases > > for a particular store (relevant loads) using C++MM and NOT pessimizing > > everything to seq_cst? > > In the general case, you can't. Acquire/release is essentially pairwise > synchronization in the C++0x MM; if you need a total order then you must > use seq_cst. I have no problem using seq_cst for either particular store or relevant loads but I don't want to pessimizing everything to seq_cst. > > However, in particular cases then you can order particular subsets. Please elaborate. > If you have an example of code that you would like to work then I can > see if I can think of a way to make it work without using seq_cst > everywhere. > > > The next question is regarding store-load fencing for particular > > release-store and subsequent acquire-load. > > One issue here is that the terminology and effects of SPARC membar > constraints do not map cleanly onto C++0x ordering constraints. SPARC Do you have an example for a C++MM's seq_cst fence actually not providing a store-load barrier in compiled code on some platform? regards, alexander.
[toc] | [prev] | [next] | [standalone]
| From | Alexander Terekhov <terekhov@web.de> |
|---|---|
| Date | 2011-06-21 18:37 +0200 |
| Message-ID | <4E00C8BE.4A910747@web.de> |
| In reply to | #343 |
Alexander Terekhov wrote:
>
> Anthony Williams wrote:
> [...]
> > > Suppose that I can program in terms of C++MM's acquire/release. The
> > > platform is x86.
> > >
> > > How am I supposed to ensure remote write atomicity ala IA-64 releases
> > > for a particular store (relevant loads) using C++MM and NOT pessimizing
> > > everything to seq_cst?
> >
> > In the general case, you can't. Acquire/release is essentially pairwise
> > synchronization in the C++0x MM; if you need a total order then you must
> > use seq_cst.
>
> I have no problem using seq_cst for either particular store or relevant
> loads ...
I take that back. I'd rather get rid of seq_cst altogether.
atomic<>'s loads and stores ought to support the following 'modes':
Whether load/store is competing (default) or not. Competing load
means that there might be concurrent store. Competing store means
that there might be concurrent load or store. Non-competing
load/store can be performed non-atomically.
Whether competing load/store needs remote write atomicity (default
is no remote write atomicity). All competing loads/stores must
specify the same remote write atomicity mode.
Whether load/store has specified reordering constraint (default
is no constraint specified) in terms of the following reordering
modes:
Whether preceding loads (in program order) can be reordered
across it (can by default).
Whether preceding stores (in program order) can be reordered
across it (can by default).
Whether subsequent loads (in program order) can be reordered
across it (can by default). For load, the set of constrained
subsequent loads can be limited to only dependant loads (aka
'consume' mode).
Whether subsequent stores (in program order) can be reordered
across it (can by default). For load, there is an implicit
reordering constraint regarding dependent stores (no need to
specify it).
atomic<>'s fence operation can be used to specify reordering
constraint using the same modes.
regards,
alexander.
[toc] | [prev] | [next] | [standalone]
| From | Alexander Terekhov <terekhov@web.de> |
|---|---|
| Date | 2011-06-21 15:59 +0200 |
| Message-ID | <4E00A3D0.82D8E955@web.de> |
| In reply to | #335 |
Anthony Williams wrote:
[... remote write atomicity ...]
> However, in particular cases then you can order particular subsets. If
> you have an example of code that you would like to work then I can see
> if I can think of a way to make it work without using seq_cst everywhere.
See examples in
http://portal.acm.org/citation.cfm?id=1375591
("4.2 Unintended Consequences of Relaxing Write-Atomicity")
"4.2.1 Write-to-Read Causality (WRC) Must be Upheld"
"4.2.2 Read-to-Write Causality (RWC)"
"4.2.3 Subtle Interplay Between Coherence and Causality"
regards,
alexander.
[toc] | [prev] | [next] | [standalone]
| From | Anthony Williams <anthony.ajw@gmail.com> |
|---|---|
| Date | 2011-06-22 09:01 -0700 |
| Message-ID | <fc7e1703-3c9f-4b25-a56a-bf7a45ce37f7@u26g2000vby.googlegroups.com> |
| In reply to | #344 |
Alexander Terekhov <terekhov@web.de> writes:
> Anthony Williams wrote:
>
> [... remote write atomicity ...]
>
>> However, in particular cases then you can order particular subsets. If
>> you have an example of code that you would like to work then I can see
>> if I can think of a way to make it work without using seq_cst everywhere.
>
> See examples in
>
> http://portal.acm.org/citation.cfm?id=1375591
> ("4.2 Unintended Consequences of Relaxing Write-Atomicity")
>
> "4.2.1 Write-to-Read Causality (WRC) Must be Upheld"
Figure 5:
std::atomic<int> X(0),Y(0);
T1
X.store(1,memory_order_relaxed);
T2
r1=X.load(memory_order_relaxed);
atomic_thread_fence(memory_order_release);
Y.store(memory_order_relaxed);
T3
r2=Y.load(memory_order_relaxed)
atomic_thread_fence(memory_order_acquire);
r3=X.load(memory_order_relaxed);
The required ordering comes from 29.8p2 and 1.10p16, since T2 stores
to
Y and T3 loads from Y: if r1==1 and r2==1 then r3==1.
> "4.2.2 Read-to-Write Causality (RWC)"
Figure 6:
std::atomic<int> X(0),Y(0);
T1
X.store(1,T1MO);
T2
r1=X.load(T2MO1);
atomic_thread_fence(T2MO2);
r2=Y.load(T2MO3);
T3
Y.store(1,T3MO1);
atomic_thread_fence(T3MO2);
r3=X.load(T3MO3);
In this case, there are no orderings such that acquire and release can
have any impact. Therefore the choice of ordering for each operation
is
either memory_order_seq_cst or memory_order_relaxed.
I presume we are trying to find a set of ordering constraints such
that
r1==1, r2==0, r3==0 is not possible.
The T1MO is memory_order_relaxed then both T2MO1 and T3MO3 must be
memory_order_seq_cst, and either of T2MO2 and T2MO3 must be
memory_order_seq_cst, and either of T3MO1 and T3MO2 must be
memory_order_seq_cst.
With any of these combinations, if r2==0 then the read of r1 must
occur
before the read of r3 in S, and r1==1, r3==0 is thus impossible by
29.3p3 (otherwise it is not consistent with the modification order of
X).
If T1MO is memory_order_seq_cst, then it is enough to make T2MO1,
T2MO2
and T3MO2 memory_order_seq_cst; the rest can be memory_order_relaxed.
If r1==1 then the load of r1 is after the store to X in S. If r2==0
then
the fence in T2 must be before the fence from T3 in S (by 29.3p5, if
the
fence in T3 is prior to the fence in T2 then r2==1). If T2 precedes T3
in S, and the store to X precedes the load of r1 in S then the store
to
X precedes T3 in S. By 29.3p5 we must have r3==1.
> "4.2.3 Subtle Interplay Between Coherence and Causality"
std::atomic<int> X(0),Y(0);
T1
X.store(1,T1MO);
T2
r1=X.load(T2MO1);
atomic_thread_fence(T2MO2);
r2=Y.load(T2MO3);
T3
Y.store(1,T3MO1);
atomic_thread_fence(T3MO2);
X.store(2,T3MO3);
T4
r3=X.load(T4MO1);
atomic_thread_fence(T4MO2);
r4=X.load(T4MO3);
In this example, the "violating result" is given as r1==1, r2==0,
r3==2,
r4==1.
r3==2, r4==1 requires that the store X=2 is prior to the store X=1 in
the modification order of X. There are no stores on thread 4, and no
ordering constraints can change this requirement, so T4MO1, T4MO2 and
T4MO3 can all be memory_order_relaxed.
The requirement that r1==1 requires that the load of r1 is seeing the
result of the store X=1, which is after the store X=2 from T3 in the
MO
of X. If T3MO3 and T2MO1, T3MO1 and T2MO3 are memory_order_seq_cst
then
everything works, even if everything else is memory_order_relaxed,
since
the load of r1 must be later in SC than the store X=2, in order to see
the later stored value, which means the store of Y=1 occurs before the
load of r2, and r2 must be 1.
Likewise, if T3MO3 and T2MO1, T3MO2 and T2MO2 are
memory_order_seq_cst,
then the same rules apply to mean the fence in T3 is before the fence
in
T2 in S, and by 29.3p5 r2==1.
It is possible that there are some alternatives with fewer
memory_order_seq_cst operations, but I don't see them right now.
Anthony
--
Author of C++ Concurrency in Action http://www.stdthread.co.uk/book/
just::thread C++0x thread library http://www.stdthread.co.uk
Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk
15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No.
5478976
[toc] | [prev] | [next] | [standalone]
| From | Anthony Williams <anthony.ajw@gmail.com> |
|---|---|
| Date | 2011-06-20 15:41 +0100 |
| Message-ID | <87sjr4r2ej.fsf@justsoftwaresolutions.co.uk> |
| In reply to | #324 |
Alexander Terekhov <terekhov@web.de> writes: > Anthony Williams wrote: >> >> Masakuni Oishi <yamasa@bsdhouse.org> writes: >> >> > If so, for the code 1 in my first post, is the outcome >> > r1 == 0 && r2 == 1 && r3 == 0 possible on IA-64? >> >> I believe so. > > Perhaps this is relevant: > > http://download.intel.com/design/itanium/downloads/25142901.pdf > > See 3.3.7.1 Total ordering of WB Releases. The example is this: > /*** code 1 ***/ > // Initially > atomic<int> x(0), y(0); > > // Thread 1: > y.store(1, memory_order_release); > atomic_thread_fence(memory_order_seq_cst); > r1 = x.load(memory_order_acquire); > > // Thread 2: > x.store(1, memory_order_release); > > // Thread 3: > r2 = x.load(memory_order_acquire); > atomic_thread_fence(memory_order_seq_cst); > r3 = y.load(memory_order_acquire); > /***************/ > > In the above code, is r1 == 0 && r2 == 1 && r3 == 0 possible? Under the C++0x memory model, the acquire and release operations here serve no purpose --- there are no stores prior to the releases, so there is no imposed ordering, and they might as well all be memory_order_relaxed. The above code is thus equivalent to the code below, as far as the C++0x memory model goes, and the compiler would be conforming if it compiled it as such: /***************/ // Initially atomic<int> x(0), y(0); // Thread 1: y.store(1, memory_order_relaxed); atomic_thread_fence(memory_order_seq_cst); r1 = x.load(memory_order_relaxed); // Thread 2: x.store(1, memory_order_relaxed); // Thread 3: r2 = x.load(memory_order_relaxed); atomic_thread_fence(memory_order_seq_cst); r3 = y.load(memory_order_relaxed); /***************/ I am not an expert on IA-64, but I would expect a relaxed write on IA-64 to be plain ST --- an unordered write --- and a relaxed load to be a plain LD --- an unordered read. Given that, the total ordering of WB releases is not relevant here, and I suspect that r1 == 0 && r2 == 1 && r3 == 0 is possible. Anthony -- Author of C++ Concurrency in Action http://www.stdthread.co.uk/book/ just::thread C++0x thread library http://www.stdthread.co.uk Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk 15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976
[toc] | [prev] | [next] | [standalone]
| From | Masakuni Oishi <yamasa@bsdhouse.org> |
|---|---|
| Date | 2011-06-20 23:24 -0700 |
| Message-ID | <cb94d252-d88e-424f-a078-92125c487f53@d1g2000prg.googlegroups.com> |
| In reply to | #336 |
Anthony Williams <anthony....@gmail.com> wrote: > Alexander Terekhov <terek...@web.de> writes: > > Anthony Williams wrote: > > >> Masakuni Oishi <yam...@bsdhouse.org> writes: > > >> > If so, for the code 1 in my first post, is the outcome > >> > r1 == 0 && r2 == 1 && r3 == 0 possible on IA-64? > > >> I believe so. > > > Perhaps this is relevant: > > >http://download.intel.com/design/itanium/downloads/25142901.pdf > > > See 3.3.7.1 Total ordering of WB Releases. > > The example is this: > > > /*** code 1 ***/ > > // Initially > > atomic<int> x(0), y(0); > > > // Thread 1: > > y.store(1, memory_order_release); > > atomic_thread_fence(memory_order_seq_cst); > > r1 = x.load(memory_order_acquire); > > > // Thread 2: > > x.store(1, memory_order_release); > > > // Thread 3: > > r2 = x.load(memory_order_acquire); > > atomic_thread_fence(memory_order_seq_cst); > > r3 = y.load(memory_order_acquire); > > /***************/ > > > In the above code, is r1 == 0 && r2 == 1 && r3 == 0 possible? > > Under the C++0x memory model, the acquire and release operations here > serve no purpose --- there are no stores prior to the releases, so there > is no imposed ordering, and they might as well all be > memory_order_relaxed. > > The above code is thus equivalent to the code below, as far as the C++0x > memory model goes, and the compiler would be conforming if it compiled > it as such: > > /***************/ > // Initially > atomic<int> x(0), y(0); > > // Thread 1: > y.store(1, memory_order_relaxed); > atomic_thread_fence(memory_order_seq_cst); > r1 = x.load(memory_order_relaxed); > > // Thread 2: > x.store(1, memory_order_relaxed); > > // Thread 3: > r2 = x.load(memory_order_relaxed); > atomic_thread_fence(memory_order_seq_cst); > r3 = y.load(memory_order_relaxed); > /***************/ > > I am not an expert on IA-64, but I would expect a relaxed write on IA-64 > to be plain ST --- an unordered write --- and a relaxed load to be a > plain LD --- an unordered read. > > Given that, the total ordering of WB releases is not relevant here, and > I suspect that r1 == 0 && r2 == 1 && r3 == 0 is possible. Hmm... Interesting. I'm not an expert on IA-64, too, but I think the code would be compiled as such: // Thread 1 US1: st [y] = 1 MF1: mf UL1: ld r1 = [x] // Thread 2 US2: st [x] = 1 // Thread 3 UL2: ld r2 = [x] MF2: mf UL3: ld r3 = [y] If the memory model of IA-64 allows ordering such as: RV_3(US2) -> F(MF2) -> F(MF1) -> RV_1(US2) then the outcome r1 == 0 && r2 == 1 && r3 == 0 is possible, I think. The Intel's specification seems not prohibiting such ordering, but I'm not sure that it may occur actually. -- masakuni
[toc] | [prev] | [next] | [standalone]
| From | Masakuni Oishi <yamasa@bsdhouse.org> |
|---|---|
| Date | 2011-06-22 10:46 -0700 |
| Message-ID | <94b2404b-ea10-4ce2-9ecf-3c150751b4fa@34g2000pru.googlegroups.com> |
| In reply to | #340 |
Masakuni Oishi <yam...@bsdhouse.org> wrote: > Anthony Williams <anthony....@gmail.com> wrote: > > Alexander Terekhov <terek...@web.de> writes: > > > Anthony Williams wrote: > > > >> Masakuni Oishi <yam...@bsdhouse.org> writes: > > > >> > If so, for the code 1 in my first post, is the outcome > > >> > r1 == 0 && r2 == 1 && r3 == 0 possible on IA-64? > > > >> I believe so. > > > > Perhaps this is relevant: > > > >http://download.intel.com/design/itanium/downloads/25142901.pdf > > > > See 3.3.7.1 Total ordering of WB Releases. > > > The example is this: > > > > /*** code 1 ***/ > > > // Initially > > > atomic<int> x(0), y(0); > > > > // Thread 1: > > > y.store(1, memory_order_release); > > > atomic_thread_fence(memory_order_seq_cst); > > > r1 = x.load(memory_order_acquire); > > > > // Thread 2: > > > x.store(1, memory_order_release); > > > > // Thread 3: > > > r2 = x.load(memory_order_acquire); > > > atomic_thread_fence(memory_order_seq_cst); > > > r3 = y.load(memory_order_acquire); > > > /***************/ > > > > In the above code, is r1 == 0 && r2 == 1 && r3 == 0 possible? > > > Under the C++0x memory model, the acquire and release operations here > > serve no purpose --- there are no stores prior to the releases, so there > > is no imposed ordering, and they might as well all be > > memory_order_relaxed. > > > The above code is thus equivalent to the code below, as far as the C++0x > > memory model goes, and the compiler would be conforming if it compiled > > it as such: > > > /***************/ > > // Initially > > atomic<int> x(0), y(0); > > > // Thread 1: > > y.store(1, memory_order_relaxed); > > atomic_thread_fence(memory_order_seq_cst); > > r1 = x.load(memory_order_relaxed); > > > // Thread 2: > > x.store(1, memory_order_relaxed); > > > // Thread 3: > > r2 = x.load(memory_order_relaxed); > > atomic_thread_fence(memory_order_seq_cst); > > r3 = y.load(memory_order_relaxed); > > /***************/ > > > I am not an expert on IA-64, but I would expect a relaxed write on IA-64 > > to be plain ST --- an unordered write --- and a relaxed load to be a > > plain LD --- an unordered read. > > > Given that, the total ordering of WB releases is not relevant here, and > > I suspect that r1 == 0 && r2 == 1 && r3 == 0 is possible. > > Hmm... Interesting. > > I'm not an expert on IA-64, too, but I think > the code would be compiled as such: > > // Thread 1 > US1: st [y] = 1 > MF1: mf > UL1: ld r1 = [x] > > // Thread 2 > US2: st [x] = 1 > > // Thread 3 > UL2: ld r2 = [x] > MF2: mf > UL3: ld r3 = [y] > > If the memory model of IA-64 allows ordering such as: > RV_3(US2) -> F(MF2) -> F(MF1) -> RV_1(US2) > then the outcome r1 == 0 && r2 == 1 && r3 == 0 is possible, > I think. > > The Intel's specification seems not prohibiting such ordering, > but I'm not sure that it may occur actually. Here is another example. /***************/ // Initially atomic<int> x(0), y(0); // Thread 1: r3 = y.load(memory_order_relaxed); atomic_thread_fence(memory_order_seq_cst); r1 = x.load(memory_order_relaxed); // Thread 2: x.store(1, memory_order_relaxed); // Thread 3: r2 = x.load(memory_order_relaxed); atomic_thread_fence(memory_order_seq_cst); y.store(1, memory_order_relaxed); /***************/ In this code, the outcome r1 == 0 && r2 == 1 && r3 == 1 is NOT allowed under the C++0x memory model. (29.8p2 and 1.10p16) But, if we compile the code on IA-64, // Thread 1 UL3: ld r3 = [y] MF1: mf UL1: ld r1 = [x] // Thread 2 US2: st [x] = 1 // Thread 3 UL2: ld r2 = [x] MF2: mf US1: st [y] = 1 it seems that the outcome r1 == 0 && r2 == 1 && r3 == 1 is possible. Isn't it? -- masakuni
[toc] | [prev] | [next] | [standalone]
| From | Masakuni Oishi <yamasa@bsdhouse.org> |
|---|---|
| Date | 2011-06-22 11:19 -0700 |
| Message-ID | <4f622dc3-ad80-4bde-ba01-28e63ffa27d7@d19g2000prh.googlegroups.com> |
| In reply to | #340 |
Masakuni Oishi <yam...@bsdhouse.org> wrote: > Anthony Williams <anthony....@gmail.com> wrote: > > Alexander Terekhov <terek...@web.de> writes: > > > Anthony Williams wrote: > > > >> Masakuni Oishi <yam...@bsdhouse.org> writes: > > > >> > If so, for the code 1 in my first post, is the outcome > > >> > r1 == 0 && r2 == 1 && r3 == 0 possible on IA-64? > > > >> I believe so. > > > > Perhaps this is relevant: > > > >http://download.intel.com/design/itanium/downloads/25142901.pdf > > > > See 3.3.7.1 Total ordering of WB Releases. > > > The example is this: > > > > /*** code 1 ***/ > > > // Initially > > > atomic<int> x(0), y(0); > > > > // Thread 1: > > > y.store(1, memory_order_release); > > > atomic_thread_fence(memory_order_seq_cst); > > > r1 = x.load(memory_order_acquire); > > > > // Thread 2: > > > x.store(1, memory_order_release); > > > > // Thread 3: > > > r2 = x.load(memory_order_acquire); > > > atomic_thread_fence(memory_order_seq_cst); > > > r3 = y.load(memory_order_acquire); > > > /***************/ > > > > In the above code, is r1 == 0 && r2 == 1 && r3 == 0 possible? > > > Under the C++0x memory model, the acquire and release operations here > > serve no purpose --- there are no stores prior to the releases, so there > > is no imposed ordering, and they might as well all be > > memory_order_relaxed. > > > The above code is thus equivalent to the code below, as far as the C++0x > > memory model goes, and the compiler would be conforming if it compiled > > it as such: > > > /***************/ > > // Initially > > atomic<int> x(0), y(0); > > > // Thread 1: > > y.store(1, memory_order_relaxed); > > atomic_thread_fence(memory_order_seq_cst); > > r1 = x.load(memory_order_relaxed); > > > // Thread 2: > > x.store(1, memory_order_relaxed); > > > // Thread 3: > > r2 = x.load(memory_order_relaxed); > > atomic_thread_fence(memory_order_seq_cst); > > r3 = y.load(memory_order_relaxed); > > /***************/ > > > I am not an expert on IA-64, but I would expect a relaxed write on IA-64 > > to be plain ST --- an unordered write --- and a relaxed load to be a > > plain LD --- an unordered read. > > > Given that, the total ordering of WB releases is not relevant here, and > > I suspect that r1 == 0 && r2 == 1 && r3 == 0 is possible. > > Hmm... Interesting. > > I'm not an expert on IA-64, too, but I think > the code would be compiled as such: > > // Thread 1 > US1: st [y] = 1 > MF1: mf > UL1: ld r1 = [x] > > // Thread 2 > US2: st [x] = 1 > > // Thread 3 > UL2: ld r2 = [x] > MF2: mf > UL3: ld r3 = [y] > > If the memory model of IA-64 allows ordering such as: > RV_3(US2) -> F(MF2) -> F(MF1) -> RV_1(US2) > then the outcome r1 == 0 && r2 == 1 && r3 == 0 is possible, > I think. > > The Intel's specification seems not prohibiting such ordering, > but I'm not sure that it may occur actually. Here is another example. /***************/ // Initially atomic<int> x(0), y(0); // Thread 1: r3 = y.load(memory_order_relaxed); atomic_thread_fence(memory_order_seq_cst); r1 = x.load(memory_order_relaxed); // Thread 2: x.store(1, memory_order_relaxed); // Thread 3: r2 = x.load(memory_order_relaxed); atomic_thread_fence(memory_order_seq_cst); y.store(1, memory_order_relaxed); /***************/ In this code, the outcome r1 == 0 && r2 == 1 && r3 == 1 is NOT allowed under the C++0x memory model. (29.8p2 and 1.10p16) But, if we compile the code on IA-64, // Thread 1 UL3: ld r3 = [y] MF1: mf UL1: ld r1 = [x] // Thread 2 US2: st [x] = 1 // Thread 3 UL2: ld r2 = [x] MF2: mf US1: st [y] = 1 it seems that the outcome r1 == 0 && r2 == 1 && r3 == 1 is possible. Isn't it? -- masakuni
[toc] | [prev] | [next] | [standalone]
| From | Masakuni Oishi <yamasa@bsdhouse.org> |
|---|---|
| Date | 2011-06-22 11:57 -0700 |
| Message-ID | <b6ee3ba2-0ae5-40da-af4c-8ed7b44fdced@z15g2000prn.googlegroups.com> |
| In reply to | #353 |
Masakuni Oishi <yam...@bsdhouse.org> wrote: > Masakuni Oishi <yam...@bsdhouse.org> wrote: > > Anthony Williams <anthony....@gmail.com> wrote: > > > Alexander Terekhov <terek...@web.de> writes: > > > > Anthony Williams wrote: > > > > >> Masakuni Oishi <yam...@bsdhouse.org> writes: > > > > >> > If so, for the code 1 in my first post, is the outcome > > > >> > r1 == 0 && r2 == 1 && r3 == 0 possible on IA-64? > > > > >> I believe so. > > > > > Perhaps this is relevant: > > > > >http://download.intel.com/design/itanium/downloads/25142901.pdf > > > > > See 3.3.7.1 Total ordering of WB Releases. > > > > The example is this: > > > > > /*** code 1 ***/ > > > > // Initially > > > > atomic<int> x(0), y(0); > > > > > // Thread 1: > > > > y.store(1, memory_order_release); > > > > atomic_thread_fence(memory_order_seq_cst); > > > > r1 = x.load(memory_order_acquire); > > > > > // Thread 2: > > > > x.store(1, memory_order_release); > > > > > // Thread 3: > > > > r2 = x.load(memory_order_acquire); > > > > atomic_thread_fence(memory_order_seq_cst); > > > > r3 = y.load(memory_order_acquire); > > > > /***************/ > > > > > In the above code, is r1 == 0 && r2 == 1 && r3 == 0 possible? > > > > Under the C++0x memory model, the acquire and release operations here > > > serve no purpose --- there are no stores prior to the releases, so there > > > is no imposed ordering, and they might as well all be > > > memory_order_relaxed. > > > > The above code is thus equivalent to the code below, as far as the C++0x > > > memory model goes, and the compiler would be conforming if it compiled > > > it as such: > > > > /***************/ > > > // Initially > > > atomic<int> x(0), y(0); > > > > // Thread 1: > > > y.store(1, memory_order_relaxed); > > > atomic_thread_fence(memory_order_seq_cst); > > > r1 = x.load(memory_order_relaxed); > > > > // Thread 2: > > > x.store(1, memory_order_relaxed); > > > > // Thread 3: > > > r2 = x.load(memory_order_relaxed); > > > atomic_thread_fence(memory_order_seq_cst); > > > r3 = y.load(memory_order_relaxed); > > > /***************/ > > > > I am not an expert on IA-64, but I would expect a relaxed write on IA-64 > > > to be plain ST --- an unordered write --- and a relaxed load to be a > > > plain LD --- an unordered read. > > > > Given that, the total ordering of WB releases is not relevant here, and > > > I suspect that r1 == 0 && r2 == 1 && r3 == 0 is possible. > > > Hmm... Interesting. > > > I'm not an expert on IA-64, too, but I think > > the code would be compiled as such: > > > // Thread 1 > > US1: st [y] = 1 > > MF1: mf > > UL1: ld r1 = [x] > > > // Thread 2 > > US2: st [x] = 1 > > > // Thread 3 > > UL2: ld r2 = [x] > > MF2: mf > > UL3: ld r3 = [y] > > > If the memory model of IA-64 allows ordering such as: > > RV_3(US2) -> F(MF2) -> F(MF1) -> RV_1(US2) > > then the outcome r1 == 0 && r2 == 1 && r3 == 0 is possible, > > I think. > > > The Intel's specification seems not prohibiting such ordering, > > but I'm not sure that it may occur actually. > > Here is another example. > > /***************/ > // Initially > atomic<int> x(0), y(0); > > // Thread 1: > r3 = y.load(memory_order_relaxed); > atomic_thread_fence(memory_order_seq_cst); > r1 = x.load(memory_order_relaxed); > > // Thread 2: > x.store(1, memory_order_relaxed); > > // Thread 3: > r2 = x.load(memory_order_relaxed); > atomic_thread_fence(memory_order_seq_cst); > y.store(1, memory_order_relaxed); > /***************/ > > In this code, the outcome r1 == 0 && r2 == 1 && r3 == 1 > is NOT allowed under the C++0x memory model. > (29.8p2 and 1.10p16) > > But, if we compile the code on IA-64, > > // Thread 1 > UL3: ld r3 = [y] > MF1: mf > UL1: ld r1 = [x] > > // Thread 2 > US2: st [x] = 1 > > // Thread 3 > UL2: ld r2 = [x] > MF2: mf > US1: st [y] = 1 > > it seems that the outcome r1 == 0 && r2 == 1 && r3 == 1 > is possible. > Isn't it? Furthermore, /***************/ // Initially atomic<int> x(0), y(0); // Thread 1: x.store(1, memory_order_relaxed); // Thread 2: r1 = x.load(memory_order_relaxed); y.store(1, memory_order_release); // Thread 3: r2 = y.load(memory_order_acquire); r3 = x.load(memory_order_relaxed); /***************/ this code does not allow the outcome r1 == 1 && r2 == 1 && r3 == 0 under the C++0x memory model. But, the compiled code on IA-64: // Thread 1 US: st [x] = 1 // Thread 2 UL1: ld r1 = [x] SR: st.rel [y] = 1 // Thread 3 LA: ld.acq r2 = [y] UL2: ld r3 = [x] seems that the outcome r1 == 1 && r2 == 1 && r3 == 0 is possible. Therefore, we may not compile a relaxed store to a plain ST. -- masakuni
[toc] | [prev] | [next] | [standalone]
| From | Alexander Terekhov <terekhov@web.de> |
|---|---|
| Date | 2011-06-27 14:05 +0200 |
| Message-ID | <4E0871F3.10EC425A@web.de> |
| In reply to | #354 |
Masakuni Oishi wrote:
[...]
> /***************/
> // Initially
> atomic<int> x(0), y(0);
>
> // Thread 1:
> x.store(1, memory_order_relaxed);
>
> // Thread 2:
> r1 = x.load(memory_order_relaxed);
> y.store(1, memory_order_release);
>
> // Thread 3:
> r2 = y.load(memory_order_acquire);
> r3 = x.load(memory_order_relaxed);
> /***************/
>
> this code does not allow the outcome
> r1 == 1 && r2 == 1 && r3 == 0
> under the C++0x memory model.
Well,
http://www.rdrop.com/users/paulmck/scalability/paper/N2745r.2011.03.04a.html
"Example 1: Load/Load ...
Thread 0:
r1 = x.load(memory_order_relaxed);
y.store(1, memory_order_release);
Thread 1:
r2 = y.load(memory_order_acquire);
r3 = x.load(memory_order_relaxed);
Thread 2 (required for assertion):
x.store(1, memory_order_relaxed);"
says that "the C++ memory model does not actually require the loads to
be ordered in this case, since thread 0's relaxed store is not
guaranteed to be seen in any particular order by thread 0's and 1's
relaxed loads. " ("thread 0's relaxed store" is meant to say "thread 2's
relaxed store" of course)
regards,
alexander.
[toc] | [prev] | [next] | [standalone]
| From | Joshua Maurice <joshuamaurice@gmail.com> |
|---|---|
| Date | 2011-06-29 16:14 -0700 |
| Message-ID | <16d29658-0b1f-441b-8686-9ee13aba51d7@r21g2000pri.googlegroups.com> |
| In reply to | #366 |
On Jun 27, 5:05 am, Alexander Terekhov <terek...@web.de> wrote:
> Masakuni Oishi wrote:
>
> [...]
>
>
>
>
>
>
>
>
>
> > /***************/
> > // Initially
> > atomic<int> x(0), y(0);
>
> > // Thread 1:
> > x.store(1, memory_order_relaxed);
>
> > // Thread 2:
> > r1 = x.load(memory_order_relaxed);
> > y.store(1, memory_order_release);
>
> > // Thread 3:
> > r2 = y.load(memory_order_acquire);
> > r3 = x.load(memory_order_relaxed);
> > /***************/
>
> > this code does not allow the outcome
> > r1 == 1 && r2 == 1 && r3 == 0
> > under the C++0x memory model.
>
> Well,
>
> http://www.rdrop.com/users/paulmck/scalability/paper/N2745r.2011.03.0...
>
> "Example 1: Load/Load ...
>
> Thread 0:
>
> r1 = x.load(memory_order_relaxed);
> y.store(1, memory_order_release);
>
> Thread 1:
>
> r2 = y.load(memory_order_acquire);
> r3 = x.load(memory_order_relaxed);
>
> Thread 2 (required for assertion):
>
> x.store(1, memory_order_relaxed);"
>
> says that "the C++ memory model does not actually require the loads to
> be ordered in this case, since thread 0's relaxed store is not
> guaranteed to be seen in any particular order by thread 0's and 1's
> relaxed loads. " ("thread 0's relaxed store" is meant to say "thread 2's
> relaxed store" of course)
Google groups is acting up, so sorry if someone's already gotten to
this.
I think you're saying that "r1 == 1 && r2 == 1 && r3 == 0" is the
result of an allowed execution according to the C++0x rules. I believe
this is incorrect. I claim that there is no such allowed execution. My
program says as much (uploaded else-thread), but I don't trust it at
the moment, so I did the reasoning myself. My reasoning is as
follows:
/***************/
// Initially
atomic<int> x(0);
atomic<int> y(0);
start thread 1;
start thread 2;
start thread 3;
// Thread 1:
x.store(1, memory_order_relaxed);
// Thread 2:
r1 = x.load(memory_order_relaxed);
y.store(1, memory_order_release);
// Thread 3:
r2 = y.load(memory_order_acquire);
r3 = x.load(memory_order_relaxed);
/***************/
//end conditions: r1 == 1 && r2 == 1 && r3 == 0
Let's see if there's an allowed execution that fits these constraints.
We'll do so by assuming the constraints. If we derive a contradiction,
then there is no allowed execution under these constraints. If we
apply all of the possible rules and do not get a contradiction, then
we've found an allowed execution.
* The constraints we're assuming are:
"r1 = x.load(memory_order_relaxed);" sees value 1
"r2 = y.load(memory_order_acquire);" sees value 1
"r3 = x.load(memory_order_relaxed);" sees value 0
* The only way to satisfy these constraints is:
"r1 = x.load(memory_order_relaxed);"
sees "x.store(1, memory_order_relaxed);"
"r2 = y.load(memory_order_acquire);"
sees "y.store(1, memory_order_release);"
"r3 = x.load(memory_order_relaxed);"
sees "atomic<int> x(0);"
* Remember:
"r2 = y.load(memory_order_acquire);"
sees "y.store(1, memory_order_release);"
* 29.3 p2 gives:
"y.store(1, memory_order_release);"
syncs-with "r2 = y.load(memory_order_acquire);"
* Repeated applications of 1.10 p11 give:
"r1 = x.load(memory_order_relaxed);"
inter-thread-hb "r3 = x.load(memory_order_relaxed);"
* 1.10 p12 gives:
"r1 = x.load(memory_order_relaxed);"
happens-before "r3 = x.load(memory_order_relaxed);"
* 1.10 p16 gives:
For T, U so that
"r1 = x.load(memory_order_relaxed);" sees T, and
"r3 = x.load(memory_order_relaxed);" sees U,
then T is U, or T precedes U in the modification order of X
aka: T <=mod-order-X U
* Thus
"x.store(1, memory_order_relaxed);"
<=mod-order-X "atomic<int> x(0);"
* 30.3.1.2 p5 gives:
"start thread 1;"
syncs-with "x.store(1, memory_order_relaxed);"
* Repeated applications of 1.10 p11 give:
"atomic<int> x(0);"
inter-thread-hb "x.store(1, memory_order_relaxed);"
* 1.10 p12 gives:
"atomic<int> x(0);"
happens-before "x.store(1, memory_order_relaxed);"
* 1.10 p15 gives:
"atomic<int> x(0);"
precedes "x.store(1, memory_order_relaxed);"
in the modification order of X
aka: "atomic<int> x(0);"
<mod-order-X "x.store(1, memory_order_relaxed);"
* So, we've derived the following:
"x.store(1, memory_order_relaxed);"
<=mod-order-X "atomic<int> x(0);"
"atomic<int> x(0);"
<mod-order-X "x.store(1, memory_order_relaxed);"
* Thus contradiction.
* Thus there is no allowed execution which satisfies the assumed
constraints.
* Aka: There is no allowed execution (in C++0x) which can produce:
r1 == 1 && r2 == 1 && r3 == 0.
[toc] | [prev] | [next] | [standalone]
| From | Anthony Williams <anthony.ajw@gmail.com> |
|---|---|
| Date | 2011-06-24 01:42 -0700 |
| Message-ID | <38d79317-4242-4f45-8840-ca6bd2cbba85@d22g2000yqn.googlegroups.com> |
| In reply to | #353 |
On Jun 22, 7:19 pm, Masakuni Oishi <yam...@bsdhouse.org> wrote: > Masakuni Oishi <yam...@bsdhouse.org> wrote: > > Anthony Williams <anthony....@gmail.com> wrote: > > > Alexander Terekhov <terek...@web.de> writes: > > > > Anthony Williams wrote: > > > > >> Masakuni Oishi <yam...@bsdhouse.org> writes: > > > > >> > If so, for the code 1 in my first post, is the outcome > > > >> > r1 == 0 && r2 == 1 && r3 == 0 possible on IA-64? > > > > >> I believe so. > > > > > Perhaps this is relevant: > > > > >http://download.intel.com/design/itanium/downloads/25142901.pdf > > > > > See 3.3.7.1 Total ordering of WB Releases. > > > > The example is this: > > > > > /*** code 1 ***/ > > > > // Initially > > > > atomic<int> x(0), y(0); > > > > > // Thread 1: > > > > y.store(1, memory_order_release); > > > > atomic_thread_fence(memory_order_seq_cst); > > > > r1 = x.load(memory_order_acquire); > > > > > // Thread 2: > > > > x.store(1, memory_order_release); > > > > > // Thread 3: > > > > r2 = x.load(memory_order_acquire); > > > > atomic_thread_fence(memory_order_seq_cst); > > > > r3 = y.load(memory_order_acquire); > > > > /***************/ > > > > > In the above code, is r1 == 0 && r2 == 1 && r3 == 0 possible? > > > > Under the C++0x memory model, the acquire and release operations here > > > serve no purpose --- there are no stores prior to the releases, so there > > > is no imposed ordering, and they might as well all be > > > memory_order_relaxed. > > > > The above code is thus equivalent to the code below, as far as the C++0x > > > memory model goes, and the compiler would be conforming if it compiled > > > it as such: > > > > /***************/ > > > // Initially > > > atomic<int> x(0), y(0); > > > > // Thread 1: > > > y.store(1, memory_order_relaxed); > > > atomic_thread_fence(memory_order_seq_cst); > > > r1 = x.load(memory_order_relaxed); > > > > // Thread 2: > > > x.store(1, memory_order_relaxed); > > > > // Thread 3: > > > r2 = x.load(memory_order_relaxed); > > > atomic_thread_fence(memory_order_seq_cst); > > > r3 = y.load(memory_order_relaxed); > > > /***************/ > > > > I am not an expert on IA-64, but I would expect a relaxed write on IA-64 > > > to be plain ST --- an unordered write --- and a relaxed load to be a > > > plain LD --- an unordered read. > > > > Given that, the total ordering of WB releases is not relevant here, and > > > I suspect that r1 == 0 && r2 == 1 && r3 == 0 is possible. > > > Hmm... Interesting. > > > I'm not an expert on IA-64, too, but I think > > the code would be compiled as such: > > > // Thread 1 > > US1: st [y] = 1 > > MF1: mf > > UL1: ld r1 = [x] > > > // Thread 2 > > US2: st [x] = 1 > > > // Thread 3 > > UL2: ld r2 = [x] > > MF2: mf > > UL3: ld r3 = [y] > > > If the memory model of IA-64 allows ordering such as: > > RV_3(US2) -> F(MF2) -> F(MF1) -> RV_1(US2) > > then the outcome r1 == 0 && r2 == 1 && r3 == 0 is possible, > > I think. > > > The Intel's specification seems not prohibiting such ordering, > > but I'm not sure that it may occur actually. > > Here is another example. > > /***************/ > // Initially > atomic<int> x(0), y(0); > > // Thread 1: > r3 = y.load(memory_order_relaxed); > atomic_thread_fence(memory_order_seq_cst); > r1 = x.load(memory_order_relaxed); > > // Thread 2: > x.store(1, memory_order_relaxed); > > // Thread 3: > r2 = x.load(memory_order_relaxed); > atomic_thread_fence(memory_order_seq_cst); > y.store(1, memory_order_relaxed); > /***************/ > > In this code, the outcome r1 == 0 && r2 == 1 && r3 == 1 > is NOT allowed under the C++0x memory model. > (29.8p2 and 1.10p16) OK > But, if we compile the code on IA-64, > > // Thread 1 > UL3: ld r3 = [y] > MF1: mf > UL1: ld r1 = [x] > > // Thread 2 > US2: st [x] = 1 > > // Thread 3 > UL2: ld r2 = [x] > MF2: mf > US1: st [y] = 1 > > it seems that the outcome r1 == 0 && r2 == 1 && r3 == 1 > is possible. > Isn't it? I'm not sure. As far as I can make out from the Itanium memory ordering docs, if r2==1 and r3==1 then: RV3(US2)->R(UL2)->F(MF2)->RV1(US1)->R(UL3)->F(MF1)->R(UL1) That on its own doesn't tell use what r1 is, since RV1(US2) is not in that chain. Unless there is something that I've missed, there is no constraint that requires RV1(US2)->R(UL1), so you are right: r1==0 is permitted. Is there anyone who is an expert on IA-64 who can confirm this, or point out what is missing? Anthony -- Author of C++ Concurrency in Action http://www.stdthread.co.uk/book/ just::thread C++0x thread library http://www.stdthread.co.uk Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk 15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976
[toc] | [prev] | [next] | [standalone]
| From | Alexander Terekhov <terekhov@web.de> |
|---|---|
| Date | 2011-06-27 13:24 +0200 |
| Message-ID | <4E086880.8F382B3D@web.de> |
| In reply to | #361 |
Anthony Williams wrote: [...] > > /***************/ > > // Initially > > atomic<int> x(0), y(0); > > > > // Thread 1: > > r3 = y.load(memory_order_relaxed); > > atomic_thread_fence(memory_order_seq_cst); > > r1 = x.load(memory_order_relaxed); > > > > // Thread 2: > > x.store(1, memory_order_relaxed); > > > > // Thread 3: > > r2 = x.load(memory_order_relaxed); > > atomic_thread_fence(memory_order_seq_cst); > > y.store(1, memory_order_relaxed); > > /***************/ > > > > In this code, the outcome r1 == 0 && r2 == 1 && r3 == 1 > > is NOT allowed under the C++0x memory model. > > (29.8p2 and 1.10p16) > > OK > > > But, if we compile the code on IA-64, > > > > // Thread 1 > > UL3: ld r3 = [y] > > MF1: mf > > UL1: ld r1 = [x] > > > > // Thread 2 > > US2: st [x] = 1 > > > > // Thread 3 > > UL2: ld r2 = [x] > > MF2: mf > > US1: st [y] = 1 > > > > it seems that the outcome r1 == 0 && r2 == 1 && r3 == 1 > > is possible. > > Isn't it? > > I'm not sure. As far as I can make out from the Itanium memory > ordering docs, if r2==1 and r3==1 then: > > RV3(US2)->R(UL2)->F(MF2)->RV1(US1)->R(UL3)->F(MF1)->R(UL1) > > That on its own doesn't tell use what r1 is, since RV1(US2) is not in > that chain. > > Unless there is something that I've missed, there is no constraint > that requires RV1(US2)->R(UL1), so you are right: r1==0 is permitted. That's because visibility of 2nd thread's store with respect to 1st thread can be delayed until after 3rd thread's store is made visible with respect 1st thread and 1st thread can load 'stale' value of x into r1 (due to lack of remote write atomicity). Itanium's st.rel aside, on PowerPC, the most heavy fence (hwsync) would prevent that outcome (hwsync in 1st thread precludes it from observing 'stale' value of x) but Itanium's mf is not that strong. regards, alexander.
[toc] | [prev] | [next] | [standalone]
| From | Anthony Williams <anthony.ajw@gmail.com> |
|---|---|
| Date | 2011-07-01 02:25 -0700 |
| Message-ID | <026f1d31-6b71-4aa0-b458-a4b21a10420e@g12g2000yqd.googlegroups.com> |
| In reply to | #365 |
On Jun 27, 12:24 pm, Alexander Terekhov <terek...@web.de> wrote: > Anthony Williams wrote: > > > /***************/ > > > // Initially > > > atomic<int> x(0), y(0); > > > > // Thread 1: > > > r3 = y.load(memory_order_relaxed); > > > atomic_thread_fence(memory_order_seq_cst); > > > r1 = x.load(memory_order_relaxed); > > > > // Thread 2: > > > x.store(1, memory_order_relaxed); > > > > // Thread 3: > > > r2 = x.load(memory_order_relaxed); > > > atomic_thread_fence(memory_order_seq_cst); > > > y.store(1, memory_order_relaxed); > > > /***************/ > > > > In this code, the outcome r1 == 0 && r2 == 1 && r3 == 1 > > > is NOT allowed under the C++0x memory model. > > > (29.8p2 and 1.10p16) > > > OK > > > > But, if we compile the code on IA-64, > > > > // Thread 1 > > > UL3: ld r3 = [y] > > > MF1: mf > > > UL1: ld r1 = [x] > > > > // Thread 2 > > > US2: st [x] = 1 > > > > // Thread 3 > > > UL2: ld r2 = [x] > > > MF2: mf > > > US1: st [y] = 1 > > > > it seems that the outcome r1 == 0 && r2 == 1 && r3 == 1 > > > is possible. > > > Isn't it? > > > I'm not sure. As far as I can make out from the Itanium memory > > ordering docs, if r2==1 and r3==1 then: > > > RV3(US2)->R(UL2)->F(MF2)->RV1(US1)->R(UL3)->F(MF1)->R(UL1) > > > That on its own doesn't tell use what r1 is, since RV1(US2) is not in > > that chain. > > > Unless there is something that I've missed, there is no constraint > > that requires RV1(US2)->R(UL1), so you are right: r1==0 is permitted. > > That's because visibility of 2nd thread's store with respect to 1st > thread can be delayed until after 3rd thread's store is made visible > with respect 1st thread and 1st thread can load 'stale' value of x into > r1 (due to lack of remote write atomicity). Itanium's st.rel aside, on > PowerPC, the most heavy fence (hwsync) would prevent that outcome > (hwsync in 1st thread precludes it from observing 'stale' value of x) > but Itanium's mf is not that strong. Right, so it appears that on Itanium we cannot use plain LD and ST for memory_order_relaxed operations --- at least one of them must be stronger. For now, I'm not sure whether we can get away with making only one stronger, or whether we need to go for making both loads and stores stronger. Anthony
[toc] | [prev] | [next] | [standalone]
Page 4 of 5 — ← Prev page 1 2 3 [4] 5 Next page →
Back to top | Article view | comp.programming.threads
csiph-web