Discussions of the Parallel Programming book
 help / color / mirror / Atom feed
From: "Paul E. McKenney" <paulmck@linux.ibm.com>
To: Akira Yokosawa <akiyks@gmail.com>
Cc: perfbook@vger.kernel.org
Subject: Re: [PATCH 2/2] count: Adjust type of variable 'counter' with code snippet
Date: Wed, 3 Oct 2018 20:40:56 -0700	[thread overview]
Message-ID: <20181004034056.GZ4222@linux.ibm.com> (raw)
In-Reply-To: <67a1d644-6289-4582-aa1b-d8f97bf4b538@gmail.com>

On Wed, Oct 03, 2018 at 07:12:32AM +0900, Akira Yokosawa wrote:
> On 2018/10/02 11:21:23 -0700, Paul E. McKenney wrote:
> > On Wed, Oct 03, 2018 at 12:24:17AM +0900, Akira Yokosawa wrote:
> >> On 2018/10/03 00:16:12 +0900, Akira Yokosawa wrote:
> >>> From a9c276c3da87ed327d003a70d60777f41999b4fc Mon Sep 17 00:00:00 2001
> >>> From: Akira Yokosawa <akiyks@gmail.com>
> >>> Date: Wed, 3 Oct 2018 00:08:49 +0900
> >>> Subject: [PATCH 2/2] count: Adjust type of variable 'counter' with code snippet
> >>>
> >>> In the actual code of count_stat.c, the per-thread variable
> >>> "counter" has the type "unsigned long".
> > 
> > Looks good, so I applied and pushed both patches, thank you!
> > 
> >> And the other description on Listing 5.3 in the text needs some reworking
> >> to reflect the changes in the snippet. Paul, can you have a look into
> >> this?
> > 
> > How does the patch below look?
> 
> Looks good to me (at least for the moment).
> 
> Acked-by: Akira Yokosawa <akiyks@gmail.com>
> 
> And I'm anticipating your expansion on the use of READ_ONCE()/WRITE_ONCE()
> in, say, somewhere in toolsoftrade. Then we would be able to reduce
> repetitive explanation here and there.

I am working on this, but there is a surprising amount to say.  So it
might take some time.  On the other hand, with the rework of the
memory-ordering chapter, this part of the Tools of the Trade chapter
seems to be the weakest part of the book, so it certainly makes sense
for me to focus there a bit.

> I'll continue to apply new scheme for other snippets in "count" chapter.

Very good, looking forward to seeing them!

							Thanx, Paul

>         Thanks, Akira
> 
> > 
> > 							Thanx, Paul
> > 
> > ------------------------------------------------------------------------
> > 
> > commit cc0409cfb0581924b05744a15fa3ebd5c1e298af
> > Author: Paul E. McKenney <paulmck@linux.ibm.com>
> > Date:   Tue Oct 2 11:19:33 2018 -0700
> > 
> >     count: Update code description and QQ based on {READ,WRITE}_ONCE()
> >     
> >     Reported-by: Akira Yokosawa <akiyks@gmail.com>
> >     Signed-off-by: Paul E. McKenney <paulmck@linux.ibm.com>
> > 
> > diff --git a/count/count.tex b/count/count.tex
> > index 9f9fd0f64838..c36e7d826a7b 100644
> > --- a/count/count.tex
> > +++ b/count/count.tex
> > @@ -495,23 +495,22 @@ show a function that increments the counters, using the
> >  thread's element of the \co{counter} array.
> >  Because this element is modified only by the corresponding thread,
> >  non-atomic increment suffices.
> > -
> > -Lines~\lnref{read:b}-\lnref{read:e}
> > -show a function that reads out the aggregate value of the counter,
> > -using the \co{for_each_thread()} primitive to iterate over the list of
> > -currently running threads, and using the \co{per_thread()} primitive
> > -to fetch the specified thread's counter.
> > -Because the hardware can fetch and store a properly aligned \co{unsigned long}
> > -atomically, and because \GCC\ is kind enough to make use of this capability,
> > -normal loads suffice, and no special atomic instructions are required.
> > -\end{lineref}
> > +However, this code uses \co{WRITE_ONCE()} to prevent destructive compiler
> > +optimizations.
> > +For but one example, the compiler is within its rights to use a
> > +to-be-stored-to location as temporary storage, thus writing what
> > +would be for all intents and purposes garbage to that location
> > +just before doing the desired store.
> > +This could of course be rather confusing to anything attempting to
> > +read out the count.
> > +The use of \co{WRITE_ONCE()} prevents this optimization and others besides.
> >  
> >  \QuickQuiz{}
> > -	What other choice does \GCC\ have, anyway???
> > +	What other nasty optimizations could \GCC\ apply?
> >  \QuickQuizAnswer{
> > -	According to the C standard, the effects of fetching a variable
> > -	that might be concurrently modified by some other thread are
> > -	undefined.
> > +	According to the C standard, the effects of doing a normal store
> > +	to a variable that might be concurrently loaded by some other
> > +	thread are undefined.
> >  	It turns out that the C standard really has no other choice,
> >  	given that C must support (for example) eight-bit architectures
> >  	which are incapable of atomically loading a \co{long}.
> > @@ -540,8 +539,10 @@ normal loads suffice, and no special atomic instructions are required.
> >  	It is therefore reasonable to expect that any Linux-kernel
> >  	adoption of C11 atomics will be incremental at best.
> >  
> > -	So why not just use plain old C-language assignment statements
> > -	to access shared variables?
> > +	But if the code is doing loads and stores that the underlying
> > +	hardware can implement with single instructions, why not just
> > +	use plain old C-language assignment statements to access shared
> > +	variables?
> >  	The problem is that the compiler is within its rights to assume
> >  	that no other thread is modifying the variable being accessed.
> >  	Given a plain old C-language load, the compiler would therefore
> > @@ -581,6 +582,22 @@ normal loads suffice, and no special atomic instructions are required.
> >  	coding standards.
> >  } \QuickQuizEnd
> >  
> > +Lines~\lnref{read:b}-\lnref{read:e}
> > +show a function that reads out the aggregate value of the counter,
> > +using the \co{for_each_thread()} primitive to iterate over the list of
> > +currently running threads, and using the \co{per_thread()} primitive
> > +to fetch the specified thread's counter.
> > +This code also uses \co{READ_ONCE()} to ensure that the compiler doesn't
> > +optimize these loads into oblivion.
> > +For but one example, a pair of consecutive calls to \co{read_count()}
> > +might be inlined, and an intrepid optimizer might notice that the same
> > +locations were being summed and thus incorrectly conclude that it would
> > +be simply wonderful to sum them once and use the resulting value twice.
> > +This sort of optimization might be rather frustrating to people expecting
> > +later \co{read_count()} calls to return larger values.
> > +The use of \co{READ_ONCE()} prevents this optimization and others besides.
> > +\end{lineref}
> > +
> >  \QuickQuiz{}
> >  	How does the per-thread \co{counter} variable in
> >  	Listing~\ref{lst:count:Array-Based Per-Thread Statistical Counters}
> > 
> 


      reply	other threads:[~2018-10-04 10:32 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-10-02 15:15 [PATCH 1/2] count: Employ new scheme for snippet from count_stat.c Akira Yokosawa
2018-10-02 15:16 ` [PATCH 2/2] count: Adjust type of variable 'counter' with code snippet Akira Yokosawa
2018-10-02 15:24   ` Akira Yokosawa
2018-10-02 18:21     ` Paul E. McKenney
2018-10-02 22:12       ` Akira Yokosawa
2018-10-04  3:40         ` Paul E. McKenney [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20181004034056.GZ4222@linux.ibm.com \
    --to=paulmck@linux.ibm.com \
    --cc=akiyks@gmail.com \
    --cc=perfbook@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox