Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c++ > #117907 > unrolled thread

Why volatile may make sense for parallel code today.

Started byBonita Montero <Bonita.Montero@gmail.com>
First post2023-11-22 17:35 +0100
Last post2023-11-25 14:46 -0800
Articles 20 on this page of 43 — 8 participants

Back to article view | Back to comp.lang.c++


Contents

  Why volatile may make sense for parallel code today. Bonita Montero <Bonita.Montero@gmail.com> - 2023-11-22 17:35 +0100
    Re: Why volatile may make sense for parallel code today. "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2023-11-22 13:22 -0800
      Re: Why volatile may make sense for parallel code today. red floyd <no.spam.here@its.invalid> - 2023-11-22 16:17 -0800
        Re: Why volatile may make sense for parallel code today. "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2023-11-22 21:05 -0800
          Re: Why volatile may make sense for parallel code today. "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2023-11-22 21:06 -0800
            Re: Why volatile may make sense for parallel code today. Marcel Mueller <news.5.maazl@spamgourmet.org> - 2023-12-01 08:50 +0100
          Re: Why volatile may make sense for parallel code today. David Brown <david.brown@hesbynett.no> - 2023-11-23 10:02 +0100
            Re: Why volatile may make sense for parallel code today. Bonita Montero <Bonita.Montero@gmail.com> - 2023-11-23 10:35 +0100
            Re: Why volatile may make sense for parallel code today. scott@slp53.sl.home (Scott Lurndal) - 2023-11-23 19:55 +0000
              Re: Why volatile may make sense for parallel code today. David Brown <david.brown@hesbynett.no> - 2023-11-24 10:08 +0100
          Re: Why volatile may make sense for parallel code today. Richard Damon <richard@damon-family.org> - 2023-11-23 11:07 -0500
            Re: Why volatile may make sense for parallel code today. Bonita Montero <Bonita.Montero@gmail.com> - 2023-11-23 17:20 +0100
              Re: Why volatile may make sense for parallel code today. Richard Damon <richard@damon-family.org> - 2023-11-23 12:50 -0500
                Re: Why volatile may make sense for parallel code today. Bonita Montero <Bonita.Montero@gmail.com> - 2023-11-24 08:57 +0100
                  Re: Why volatile may make sense for parallel code today. "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2023-11-24 00:16 -0800
                    Re: Why volatile may make sense for parallel code today. Bonita Montero <Bonita.Montero@gmail.com> - 2023-11-24 09:30 +0100
                      Re: Why volatile may make sense for parallel code today. "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2023-11-24 01:04 -0800
                        Re: Why volatile may make sense for parallel code today. "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2023-11-24 01:05 -0800
                Re: Why volatile may make sense for parallel code today. David Brown <david.brown@hesbynett.no> - 2023-11-24 10:23 +0100
              Re: Why volatile may make sense for parallel code today. "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2023-11-23 22:05 -0800
                Re: Why volatile may make sense for parallel code today. "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2023-11-23 22:53 -0800
                Re: Why volatile may make sense for parallel code today. Bonita Montero <Bonita.Montero@gmail.com> - 2023-11-24 08:53 +0100
                  Re: Why volatile may make sense for parallel code today. "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2023-11-24 01:06 -0800
                    Re: Why volatile may make sense for parallel code today. Bonita Montero <Bonita.Montero@gmail.com> - 2023-11-24 10:10 +0100
              Re: Why volatile may make sense for parallel code today. "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2023-11-24 01:14 -0800
                Re: Why volatile may make sense for parallel code today. "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2023-11-24 15:32 -0800
      Re: Why volatile may make sense for parallel code today. Bonita Montero <Bonita.Montero@gmail.com> - 2023-11-23 08:08 +0100
        Re: Why volatile may make sense for parallel code today. Kaz Kylheku <864-117-4973@kylheku.com> - 2023-11-23 08:26 +0000
          Re: Why volatile may make sense for parallel code today. Bonita Montero <Bonita.Montero@gmail.com> - 2023-11-23 09:31 +0100
            Re: Why volatile may make sense for parallel code today. Bonita Montero <Bonita.Montero@gmail.com> - 2023-11-23 15:39 +0100
        Re: Why volatile may make sense for parallel code today. scott@slp53.sl.home (Scott Lurndal) - 2023-11-23 19:56 +0000
          Re: Why volatile may make sense for parallel code today. Bonita Montero <Bonita.Montero@gmail.com> - 2023-11-24 05:26 +0100
            Re: Why volatile may make sense for parallel code today. "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2023-11-23 21:53 -0800
            Re: Why volatile may make sense for parallel code today. "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2023-11-23 21:59 -0800
          Re: Why volatile may make sense for parallel code today. "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2023-11-23 21:47 -0800
    Re: Why volatile may make sense for parallel code today. Kaz Kylheku <864-117-4973@kylheku.com> - 2023-11-23 20:32 +0000
      Re: Why volatile may make sense for parallel code today. Bonita Montero <Bonita.Montero@gmail.com> - 2023-11-24 05:27 +0100
        Re: Why volatile may make sense for parallel code today. "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2023-11-23 21:55 -0800
        Re: Why volatile may make sense for parallel code today. David Brown <david.brown@hesbynett.no> - 2023-11-24 10:35 +0100
        Re: Why volatile may make sense for parallel code today. Kaz Kylheku <864-117-4973@kylheku.com> - 2023-11-24 18:27 +0000
          Re: Why volatile may make sense for parallel code today. "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2023-11-24 15:37 -0800
          Re: Why volatile may make sense for parallel code today. Bonita Montero <Bonita.Montero@gmail.com> - 2023-11-25 13:11 +0100
            Re: Why volatile may make sense for parallel code today. "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2023-11-25 14:46 -0800

Page 1 of 3  [1] 2 3  Next page →


#117907 — Why volatile may make sense for parallel code today.

FromBonita Montero <Bonita.Montero@gmail.com>
Date2023-11-22 17:35 +0100
SubjectWhy volatile may make sense for parallel code today.
Message-ID<ujlajk$1dalh$1@raubtier-asyl.eternal-september.org>
#include <Windows.h>
#include <thread>

using namespace std;

int main()
{
	constexpr size_t ROUNDS = 1'000'000;
	size_t volatile r = 1'000'000;
	jthread thr( [&]()
		{
			while( r )
				SleepEx( INFINITE, TRUE );
		} );
	for( size_t r = ROUNDS; r--; )
		QueueUserAPC( (PAPCFUNC)[]( auto p ) { --*(size_t*)p; }, 
thr.native_handle(), (ULONG_PTR)&r );
}

[toc] | [next] | [standalone]


#117908

From"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>
Date2023-11-22 13:22 -0800
Message-ID<ujlrdv$1g6ej$1@dont-email.me>
In reply to#117907
On 11/22/2023 8:35 AM, Bonita Montero wrote:
> #include <Windows.h>
> #include <thread>
> 
> using namespace std;
> 
> int main()
> {
>      constexpr size_t ROUNDS = 1'000'000;
>      size_t volatile r = 1'000'000;
>      jthread thr( [&]()
>          {
>              while( r )
>                  SleepEx( INFINITE, TRUE );
>          } );
>      for( size_t r = ROUNDS; r--; )
>          QueueUserAPC( (PAPCFUNC)[]( auto p ) { --*(size_t*)p; }, 
> thr.native_handle(), (ULONG_PTR)&r );
> }

std::atomic<size_t> r

[toc] | [prev] | [next] | [standalone]


#117909

Fromred floyd <no.spam.here@its.invalid>
Date2023-11-22 16:17 -0800
Message-ID<ujm5n6$1hok4$1@redfloyd.dont-email.me>
In reply to#117908
On 11/22/2023 1:22 PM, Chris M. Thomasson wrote:
> On 11/22/2023 8:35 AM, Bonita Montero wrote:
>> #include <Windows.h>
>> #include <thread>
>>
>> using namespace std;
>>
>> int main()
>> {
>>      constexpr size_t ROUNDS = 1'000'000;
>>      size_t volatile r = 1'000'000;
>>      jthread thr( [&]()
>>          {
>>              while( r )
>>                  SleepEx( INFINITE, TRUE );
>>          } );
>>      for( size_t r = ROUNDS; r--; )
>>          QueueUserAPC( (PAPCFUNC)[]( auto p ) { --*(size_t*)p; }, 
>> thr.native_handle(), (ULONG_PTR)&r );
>> }
> 
> std::atomic<size_t> r
> 

I'm confused.  Does std:atomic imply "do not optimize access to this
variable"?  Because if it doesn't, then I can see how the "while (r)"
loop can just spin.

[toc] | [prev] | [next] | [standalone]


#117910

From"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>
Date2023-11-22 21:05 -0800
Message-ID<ujmmia$1nmms$1@dont-email.me>
In reply to#117909
On 11/22/2023 4:17 PM, red floyd wrote:
> On 11/22/2023 1:22 PM, Chris M. Thomasson wrote:
>> On 11/22/2023 8:35 AM, Bonita Montero wrote:
>>> #include <Windows.h>
>>> #include <thread>
>>>
>>> using namespace std;
>>>
>>> int main()
>>> {
>>>      constexpr size_t ROUNDS = 1'000'000;
>>>      size_t volatile r = 1'000'000;
>>>      jthread thr( [&]()
>>>          {
>>>              while( r )
>>>                  SleepEx( INFINITE, TRUE );
>>>          } );
>>>      for( size_t r = ROUNDS; r--; )
>>>          QueueUserAPC( (PAPCFUNC)[]( auto p ) { --*(size_t*)p; }, 
>>> thr.native_handle(), (ULONG_PTR)&r );
>>> }
>>
>> std::atomic<size_t> r
>>
> 
> I'm confused.  Does std:atomic imply "do not optimize access to this
> variable"?  Because if it doesn't, then I can see how the "while (r)"
> loop can just spin.
> 
> 

std::atomic should honor a read, when you read it even from 
std::memory_order_relaxed. If not, imvvvvhhooo, its broken?

[toc] | [prev] | [next] | [standalone]


#117911

From"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>
Date2023-11-22 21:06 -0800
Message-ID<ujmmki$1nmms$2@dont-email.me>
In reply to#117910
On 11/22/2023 9:05 PM, Chris M. Thomasson wrote:
> On 11/22/2023 4:17 PM, red floyd wrote:
>> On 11/22/2023 1:22 PM, Chris M. Thomasson wrote:
>>> On 11/22/2023 8:35 AM, Bonita Montero wrote:
>>>> #include <Windows.h>
>>>> #include <thread>
>>>>
>>>> using namespace std;
>>>>
>>>> int main()
>>>> {
>>>>      constexpr size_t ROUNDS = 1'000'000;
>>>>      size_t volatile r = 1'000'000;
>>>>      jthread thr( [&]()
>>>>          {
>>>>              while( r )
>>>>                  SleepEx( INFINITE, TRUE );
>>>>          } );
>>>>      for( size_t r = ROUNDS; r--; )
>>>>          QueueUserAPC( (PAPCFUNC)[]( auto p ) { --*(size_t*)p; }, 
>>>> thr.native_handle(), (ULONG_PTR)&r );
>>>> }
>>>
>>> std::atomic<size_t> r
>>>
>>
>> I'm confused.  Does std:atomic imply "do not optimize access to this
>> variable"?  Because if it doesn't, then I can see how the "while (r)"
>> loop can just spin.
>>
>>
> 
> std::atomic should honor a read, when you read it even from 
> std::memory_order_relaxed. If not, imvvvvhhooo, its broken?

Afaict, std::atomic should imply volatile? Right? If not, please correct me!

[toc] | [prev] | [next] | [standalone]


#118014

FromMarcel Mueller <news.5.maazl@spamgourmet.org>
Date2023-12-01 08:50 +0100
Message-ID<ukc37c$1to4s$3@gwaiyur.mb-net.net>
In reply to#117911
Am 23.11.23 um 06:06 schrieb Chris M. Thomasson:
> Afaict, std::atomic should imply volatile? Right? If not, please correct 
> me!

In practice yes. But is this required by the standard? I could not find 
any hint. Strictly speaking it is still required.

In fact memory ordering does not guarantee any particular time when the 
change appears at another thread. So there is always some delay. But 
could it be infinite? So the compiler could cache anything if no other 
memory access according to the memory barrier is generated by the code? 
This applies to read and write.
But I think it is almost impossible to write any reasonable code, that 
causes no other memory access that forces the atomic value to be read or 
written.


Marcel

[toc] | [prev] | [next] | [standalone]


#117915

FromDavid Brown <david.brown@hesbynett.no>
Date2023-11-23 10:02 +0100
Message-ID<ujn4g3$1pevs$1@dont-email.me>
In reply to#117910
On 23/11/2023 06:05, Chris M. Thomasson wrote:
> On 11/22/2023 4:17 PM, red floyd wrote:
>> On 11/22/2023 1:22 PM, Chris M. Thomasson wrote:
>>> On 11/22/2023 8:35 AM, Bonita Montero wrote:
>>>> #include <Windows.h>
>>>> #include <thread>
>>>>
>>>> using namespace std;
>>>>
>>>> int main()
>>>> {
>>>>      constexpr size_t ROUNDS = 1'000'000;
>>>>      size_t volatile r = 1'000'000;
>>>>      jthread thr( [&]()
>>>>          {
>>>>              while( r )
>>>>                  SleepEx( INFINITE, TRUE );
>>>>          } );
>>>>      for( size_t r = ROUNDS; r--; )
>>>>          QueueUserAPC( (PAPCFUNC)[]( auto p ) { --*(size_t*)p; }, 
>>>> thr.native_handle(), (ULONG_PTR)&r );
>>>> }
>>>
>>> std::atomic<size_t> r
>>>
>>
>> I'm confused.  Does std:atomic imply "do not optimize access to this
>> variable"?  Because if it doesn't, then I can see how the "while (r)"
>> loop can just spin.
>>
>>
> 
> std::atomic should honor a read, when you read it even from 
> std::memory_order_relaxed. If not, imvvvvhhooo, its broken?


You will probably find that compilers in practice will re-read "r" each 
round of the loop, regardless of the memory order.  I am not convinced 
this would be required for "relaxed", but compilers generally do not 
optimise atomics as much as they are allowed to.  They are, as far as I 
have seen in my far from comprehensive testing, treated as though 
"atomic" implied "volatile".

But as far as I can tell from the C and C++ standards, "atomic" does not 
imply "volatile".  There are situations where atomics can be "optimised" 
- re-ordered with respect to other code, or simplified - while volatile 
atomics cannot.  I can see no reason why adjacent non-volatile relaxed 
atomic reads of the same object cannot be combined, even if separated by 
other code (with no volatile or atomic accesses).  The same goes for 
writes.  If you have :

	std::atomic<int> ax = 100;

	...

	x = 1;
	x += 2;
	x = x * x;

then you are guaranteed that any other thread reading "ax" will see 
either the old value (100, if it was not changed), or the final value of 
9.  It /might/ also see values of 1 or 3 along the way, but there is no 
requirement for the code to produce these intermediate values or for 
them to be visible to other threads.

At least, that is how I interpret things.  And I believe the fact that 
the C and C++ standards make a distinction between atomics and volatile 
atomics indicates that the standard authors do not see "atomic" as 
implying the semantics of "volatile" - even if compiler writers choose 
to act that way.


I personally thing it was a terrible mistake to mix sequencing and 
ordering with atomics when multi-threading was introduced to the C and 
C++ standards.  Atomics would have been simpler, more efficient, and 
consistent with their naming if their semantics had not included any 
kind of synchronisation.  Synchronisation and ordering is a very 
different concept from atomic access, and should be covered differently 
(by fences of various sorts).

[toc] | [prev] | [next] | [standalone]


#117916

FromBonita Montero <Bonita.Montero@gmail.com>
Date2023-11-23 10:35 +0100
Message-ID<ujn6d1$1pnpk$1@raubtier-asyl.eternal-september.org>
In reply to#117915
Am 23.11.2023 um 10:02 schrieb David Brown:

> I am not convinced ....
> ... but compilers generally do not optimise atomics as much as they are allowed to.

Is there some kind of contradiction ?

[toc] | [prev] | [next] | [standalone]


#117921

Fromscott@slp53.sl.home (Scott Lurndal)
Date2023-11-23 19:55 +0000
Message-ID<P6O7N.94356$BbXa.42252@fx16.iad>
In reply to#117915
David Brown <david.brown@hesbynett.no> writes:
>On 23/11/2023 06:05, Chris M. Thomasson wrote:
>> On 11/22/2023 4:17 PM, red floyd wrote:
>>> On 11/22/2023 1:22 PM, Chris M. Thomasson wrote:
>>>> On 11/22/2023 8:35 AM, Bonita Montero wrote:
>>>>> #include <Windows.h>
>>>>> #include <thread>
>>>>>
>>>>> using namespace std;
>>>>>
>>>>> int main()
>>>>> {
>>>>>      constexpr size_t ROUNDS = 1'000'000;
>>>>>      size_t volatile r = 1'000'000;
>>>>>      jthread thr( [&]()
>>>>>          {
>>>>>              while( r )
>>>>>                  SleepEx( INFINITE, TRUE );
>>>>>          } );
>>>>>      for( size_t r = ROUNDS; r--; )
>>>>>          QueueUserAPC( (PAPCFUNC)[]( auto p ) { --*(size_t*)p; }, 
>>>>> thr.native_handle(), (ULONG_PTR)&r );
>>>>> }
>>>>
>>>> std::atomic<size_t> r
>>>>
>>>
>>> I'm confused.  Does std:atomic imply "do not optimize access to this
>>> variable"?  Because if it doesn't, then I can see how the "while (r)"
>>> loop can just spin.
>>>
>>>
>> 
>> std::atomic should honor a read, when you read it even from 
>> std::memory_order_relaxed. If not, imvvvvhhooo, its broken?
>
>
>You will probably find that compilers in practice will re-read "r" each 
>round of the loop, regardless of the memory order.  I am not convinced 
>this would be required for "relaxed", but compilers generally do not 
>optimise atomics as much as they are allowed to.  They are, as far as I 
>have seen in my far from comprehensive testing, treated as though 
>"atomic" implied "volatile".

Linux tends to apply the volatile qualifier on the access, rather
than the definition.

#define ACCESS_ONCE(x) (*(volatile __typeof__(x) *)&(x))

 while (ACCESS_ONCE(r)) {
 }

Makes it rather obvious when reading the code what the intent
is, and won't be affected of someone accidentially removes the
volatile qualifier from the declaration of r.

Works just fine in c++, too.

[toc] | [prev] | [next] | [standalone]


#117944

FromDavid Brown <david.brown@hesbynett.no>
Date2023-11-24 10:08 +0100
Message-ID<ujpp6k$28uia$1@dont-email.me>
In reply to#117921
On 23/11/2023 20:55, Scott Lurndal wrote:
> David Brown <david.brown@hesbynett.no> writes:
>> On 23/11/2023 06:05, Chris M. Thomasson wrote:
>>> On 11/22/2023 4:17 PM, red floyd wrote:
>>>> On 11/22/2023 1:22 PM, Chris M. Thomasson wrote:
>>>>> On 11/22/2023 8:35 AM, Bonita Montero wrote:
>>>>>> #include <Windows.h>
>>>>>> #include <thread>
>>>>>>
>>>>>> using namespace std;
>>>>>>
>>>>>> int main()
>>>>>> {
>>>>>>       constexpr size_t ROUNDS = 1'000'000;
>>>>>>       size_t volatile r = 1'000'000;
>>>>>>       jthread thr( [&]()
>>>>>>           {
>>>>>>               while( r )
>>>>>>                   SleepEx( INFINITE, TRUE );
>>>>>>           } );
>>>>>>       for( size_t r = ROUNDS; r--; )
>>>>>>           QueueUserAPC( (PAPCFUNC)[]( auto p ) { --*(size_t*)p; },
>>>>>> thr.native_handle(), (ULONG_PTR)&r );
>>>>>> }
>>>>>
>>>>> std::atomic<size_t> r
>>>>>
>>>>
>>>> I'm confused.  Does std:atomic imply "do not optimize access to this
>>>> variable"?  Because if it doesn't, then I can see how the "while (r)"
>>>> loop can just spin.
>>>>
>>>>
>>>
>>> std::atomic should honor a read, when you read it even from
>>> std::memory_order_relaxed. If not, imvvvvhhooo, its broken?
>>
>>
>> You will probably find that compilers in practice will re-read "r" each
>> round of the loop, regardless of the memory order.  I am not convinced
>> this would be required for "relaxed", but compilers generally do not
>> optimise atomics as much as they are allowed to.  They are, as far as I
>> have seen in my far from comprehensive testing, treated as though
>> "atomic" implied "volatile".
> 
> Linux tends to apply the volatile qualifier on the access, rather
> than the definition.
> 
> #define ACCESS_ONCE(x) (*(volatile __typeof__(x) *)&(x))
> 
>   while (ACCESS_ONCE(r)) {
>   }
> 
> Makes it rather obvious when reading the code what the intent
> is, and won't be affected of someone accidentially removes the
> volatile qualifier from the declaration of r.
> 
> Works just fine in c++, too.

That is often my preference too, since it is the access that is 
"volatile" - a "volatile object" is simply one for which all accesses 
are "volatile".

For the pedants, it might be worth noting that the "cast to pointer to 
volatile" technique of ACCESS_ONCE is not actually guaranteed to be 
treated as a volatile access in C until C17/C18 when the wording was 
changed to talk about accesses via "volatile lvalues" rather than 
accesses to objects declared as volatile.  (When the topic was discussed 
by the committee, everyone agreed that all known compiler vendors 
treated "cast to pointer to volatile" accesses as volatile, so the 
change was a formality rather than any practical difference.)  I don't 
know if and when this change was added to C++.

[toc] | [prev] | [next] | [standalone]


#117918

FromRichard Damon <richard@damon-family.org>
Date2023-11-23 11:07 -0500
Message-ID<ujntc3$1p191$1@i2pn2.org>
In reply to#117910
On 11/23/23 12:05 AM, Chris M. Thomasson wrote:
> On 11/22/2023 4:17 PM, red floyd wrote:
>> On 11/22/2023 1:22 PM, Chris M. Thomasson wrote:
>>> On 11/22/2023 8:35 AM, Bonita Montero wrote:
>>>> #include <Windows.h>
>>>> #include <thread>
>>>>
>>>> using namespace std;
>>>>
>>>> int main()
>>>> {
>>>>      constexpr size_t ROUNDS = 1'000'000;
>>>>      size_t volatile r = 1'000'000;
>>>>      jthread thr( [&]()
>>>>          {
>>>>              while( r )
>>>>                  SleepEx( INFINITE, TRUE );
>>>>          } );
>>>>      for( size_t r = ROUNDS; r--; )
>>>>          QueueUserAPC( (PAPCFUNC)[]( auto p ) { --*(size_t*)p; }, 
>>>> thr.native_handle(), (ULONG_PTR)&r );
>>>> }
>>>
>>> std::atomic<size_t> r
>>>
>>
>> I'm confused.  Does std:atomic imply "do not optimize access to this
>> variable"?  Because if it doesn't, then I can see how the "while (r)"
>> loop can just spin.
>>
>>
> 
> std::atomic should honor a read, when you read it even from 
> std::memory_order_relaxed. If not, imvvvvhhooo, its broken?

My understanding is that std:atomic needs to honor a read in the sense 
that it wlll get the most recent value that has happened "before" the 
read (as determined by memory order).

So, if nothing in the loop can establish a time order with respect to 
other threads, then it should be allowed for the compiler to optimize 
out the read. SleepEx could (and should) establish time order, so the 
compiler can't, in this case, optimize the read away.

[toc] | [prev] | [next] | [standalone]


#117919

FromBonita Montero <Bonita.Montero@gmail.com>
Date2023-11-23 17:20 +0100
Message-ID<ujnu49$1t7eu$1@raubtier-asyl.eternal-september.org>
In reply to#117918
Am 23.11.2023 um 17:07 schrieb Richard Damon:

> My understanding is that std:atomic needs to honor a read in the sense 
> that it wlll get the most recent value that has happened "before" the 
> read (as determined by memory order).

... and the read is atomic - even if the trivial object is 1kB in size.

> So, if nothing in the loop can establish a time order with respect to 
> other threads, then it should be allowed for the compiler to optimize 
> out the read. ...

An atomic doesn't cache repeatable reads. The order memory-consistency
parameter is just for the ordering of other reads and writes.


[toc] | [prev] | [next] | [standalone]


#117920

FromRichard Damon <richard@damon-family.org>
Date2023-11-23 12:50 -0500
Message-ID<ujo3dr$1p192$1@i2pn2.org>
In reply to#117919
On 11/23/23 11:20 AM, Bonita Montero wrote:
> Am 23.11.2023 um 17:07 schrieb Richard Damon:
> 
>> My understanding is that std:atomic needs to honor a read in the sense 
>> that it wlll get the most recent value that has happened "before" the 
>> read (as determined by memory order).
> 
> ... and the read is atomic - even if the trivial object is 1kB in size.

Yes, which has nothing to do with the question.

> 
>> So, if nothing in the loop can establish a time order with respect to 
>> other threads, then it should be allowed for the compiler to optimize 
>> out the read. ...
> 
> An atomic doesn't cache repeatable reads. The order memory-consistency
> parameter is just for the ordering of other reads and writes.
> 

Yes, the atomic itself doesn't "cache" the data, but as far as I read, 
there is no requirement to refetch the data if the code still has the 
old value around, and it hasn't been invalidated by possible memory 
ordering.

If there can't be a write "before" the second read, that wasn't also 
also "after" the first read, then there is no requirement to refetch the 
data. In relaxed memory orders, just being physically before isn't 
enough to be "before", but you need some explicit "barrier" to establish it.

I will admit this isn't an area I consider myself an expert in, but I 
find no words that prohibit the optimization. The implementation does 
need to consider possible action by other "threads" but only as far a 
constrained by memory order, so two reads in the same ordering "slot" 
are not forced.

[toc] | [prev] | [next] | [standalone]


#117937

FromBonita Montero <Bonita.Montero@gmail.com>
Date2023-11-24 08:57 +0100
Message-ID<ujpl1a$28aoq$3@raubtier-asyl.eternal-september.org>
In reply to#117920
Am 23.11.2023 um 18:50 schrieb Richard Damon:

> Yes, the atomic itself doesn't "cache" the data, but as far as I read, 
> there is no requirement to refetch the data if the code still has the 
> old value around, and it hasn't been invalidated by possible memory 
> ordering.

I don't believe that, think about an atomic flag that is periodically
polled. The compiler shouldn't cache that value.

[toc] | [prev] | [next] | [standalone]


#117939

From"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>
Date2023-11-24 00:16 -0800
Message-ID<ujpm48$28gcu$1@dont-email.me>
In reply to#117937
On 11/23/2023 11:57 PM, Bonita Montero wrote:
> Am 23.11.2023 um 18:50 schrieb Richard Damon:
> 
>> Yes, the atomic itself doesn't "cache" the data, but as far as I read, 
>> there is no requirement to refetch the data if the code still has the 
>> old value around, and it hasn't been invalidated by possible memory 
>> ordering.
> 
> I don't believe that, think about an atomic flag that is periodically
> polled. The compiler shouldn't cache that value.
> 
> 

std::atomic is going to work for such a flag. Depending on your setup, 
it should be using std::memory_order_relaxed for the polling.

[toc] | [prev] | [next] | [standalone]


#117940

FromBonita Montero <Bonita.Montero@gmail.com>
Date2023-11-24 09:30 +0100
Message-ID<ujpmue$28j0j$1@raubtier-asyl.eternal-september.org>
In reply to#117939
Am 24.11.2023 um 09:16 schrieb Chris M. Thomasson:

> std::atomic is going to work for such a flag. Depending on your
> setup, it should be using std::memory_order_relaxed for the polling.

There's also atomic_flag, but it has some limitations over atomic_bool
that I've never used it. You can set it only in conjunction with an
atomic read and I never had a use for that. And this relies on a atomic
exchange, which costs a lot more than just a byte write.

[toc] | [prev] | [next] | [standalone]


#117941

From"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>
Date2023-11-24 01:04 -0800
Message-ID<ujpovj$28srl$1@dont-email.me>
In reply to#117940
On 11/24/2023 12:30 AM, Bonita Montero wrote:
> Am 24.11.2023 um 09:16 schrieb Chris M. Thomasson:
> 
>> std::atomic is going to work for such a flag. Depending on your
>> setup, it should be using std::memory_order_relaxed for the polling.
> 
> There's also atomic_flag, but it has some limitations over atomic_bool
> that I've never used it. You can set it only in conjunction with an
> atomic read and I never had a use for that. And this relies on a atomic
> exchange, which costs a lot more than just a byte write.

Fwiw, this flag should be aligned on a l2 cache line boundary, and 
padded up to a l2 cache line size.

[toc] | [prev] | [next] | [standalone]


#117942

From"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>
Date2023-11-24 01:05 -0800
Message-ID<ujpp19$28srl$2@dont-email.me>
In reply to#117941
On 11/24/2023 1:04 AM, Chris M. Thomasson wrote:
> On 11/24/2023 12:30 AM, Bonita Montero wrote:
>> Am 24.11.2023 um 09:16 schrieb Chris M. Thomasson:
>>
>>> std::atomic is going to work for such a flag. Depending on your
>>> setup, it should be using std::memory_order_relaxed for the polling.
>>
>> There's also atomic_flag, but it has some limitations over atomic_bool
>> that I've never used it. You can set it only in conjunction with an
>> atomic read and I never had a use for that. And this relies on a atomic
>> exchange, which costs a lot more than just a byte write.
> 
> Fwiw, this flag should be aligned on a l2 cache line boundary, and 
> padded up to a l2 cache line size.

You can stuff a cache line with words, as long as you do not straddle a 
cache line boundary... YIKES!

[toc] | [prev] | [next] | [standalone]


#117949

FromDavid Brown <david.brown@hesbynett.no>
Date2023-11-24 10:23 +0100
Message-ID<ujpq1k$28uia$2@dont-email.me>
In reply to#117920
On 23/11/2023 18:50, Richard Damon wrote:
> On 11/23/23 11:20 AM, Bonita Montero wrote:
>> Am 23.11.2023 um 17:07 schrieb Richard Damon:
>>
>>> My understanding is that std:atomic needs to honor a read in the 
>>> sense that it wlll get the most recent value that has happened 
>>> "before" the read (as determined by memory order).
>>
>> ... and the read is atomic - even if the trivial object is 1kB in size.
> 
> Yes, which has nothing to do with the question.
> 
>>
>>> So, if nothing in the loop can establish a time order with respect to 
>>> other threads, then it should be allowed for the compiler to optimize 
>>> out the read. ...
>>
>> An atomic doesn't cache repeatable reads. The order memory-consistency
>> parameter is just for the ordering of other reads and writes.
>>
> 
> Yes, the atomic itself doesn't "cache" the data, but as far as I read, 
> there is no requirement to refetch the data if the code still has the 
> old value around, and it hasn't been invalidated by possible memory 
> ordering.
> 
> If there can't be a write "before" the second read, that wasn't also 
> also "after" the first read, then there is no requirement to refetch the 
> data. In relaxed memory orders, just being physically before isn't 
> enough to be "before", but you need some explicit "barrier" to establish 
> it.
> 
> I will admit this isn't an area I consider myself an expert in, but I 
> find no words that prohibit the optimization. The implementation does 
> need to consider possible action by other "threads" but only as far a 
> constrained by memory order, so two reads in the same ordering "slot" 
> are not forced.

That is exactly how I see it (I also do not consider myself an expert in 
this area).  I cannot see any requirement in the description of the 
execution, covering sequencing, ordering, "happens before", and all the 
rest, that suggests that the number of atomic accesses, or their order 
amongst each other, or their order with respect to volatile accesses or 
non-volatile accesses, is forced to follow the source code except where 
the atomics have specific sequencing.  Atomic accesses are not 
"volatile" - they are not, in themselves, "observable behaviour".

Because the the sequencing requirements for atomics depends partly on 
things happening in other threads, compilers are much more limited in 
how they can re-order or otherwise optimise atomic accesses than they 
are for normal accesses (unless the compiler knows all about the other 
threads too!).  Compilers must be pessimistic about optimisation.  But 
for certain simple cases, such as multiple neighbouring atomic reads of 
the same address or multiple neighbouring writes to the same address, I 
can't see any reason why they cannot be combined.

(Again, I am not an expert here - and I will be happy to be corrected. 
They say the best way to learn something on the internet is not by 
asking questions, but by writing something that is wrong!)

[toc] | [prev] | [next] | [standalone]


#117933

From"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>
Date2023-11-23 22:05 -0800
Message-ID<ujpefk$27eto$2@dont-email.me>
In reply to#117919
On 11/23/2023 8:20 AM, Bonita Montero wrote:
> Am 23.11.2023 um 17:07 schrieb Richard Damon:
> 
>> My understanding is that std:atomic needs to honor a read in the sense 
>> that it wlll get the most recent value that has happened "before" the 
>> read (as determined by memory order).
> 
> ... and the read is atomic - even if the trivial object is 1kB in size.

humm.. Say, the read is from a word in memory. Define your trivial 
object, POD, l2 cache line sized, and aligned on a l2 cache line 
boundary? Are you refering to how certain arch works?

> 
>> So, if nothing in the loop can establish a time order with respect to 
>> other threads, then it should be allowed for the compiler to optimize 
>> out the read. ...
> 
> An atomic doesn't cache repeatable reads. The order memory-consistency
> parameter is just for the ordering of other reads and writes.
> 
> 
> 

[toc] | [prev] | [next] | [standalone]


Page 1 of 3  [1] 2 3  Next page →

Back to top | Article view | comp.lang.c++


csiph-web