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


Groups > linux.kernel > #1730016 > unrolled thread

Re: [lkp-robot] [sched/fair] 6d46bd3d97: netperf.Throughput_tps -11.3% regression

Started byJoel Fernandes <joelaf@google.com>
First post2017-09-10 19:00 +0200
Last post2017-09-25 01:50 +0200
Articles 11 — 3 participants

Back to article view | Back to linux.kernel

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: [lkp-robot] [sched/fair] 6d46bd3d97: netperf.Throughput_tps  -11.3% regression Joel Fernandes <joelaf@google.com> - 2017-09-10 19:00 +0200
    Re: [lkp-robot] [sched/fair] 6d46bd3d97: netperf.Throughput_tps  -11.3% regression Mike Galbraith <efault@gmx.de> - 2017-09-11 05:00 +0200
      Re: [lkp-robot] [sched/fair] 6d46bd3d97: netperf.Throughput_tps  -11.3% regression Joel Fernandes <joelaf@google.com> - 2017-09-11 08:40 +0200
        Re: [lkp-robot] [sched/fair] 6d46bd3d97: netperf.Throughput_tps  -11.3% regression Mike Galbraith <efault@gmx.de> - 2017-09-11 10:10 +0200
        Re: [lkp-robot] [sched/fair] 6d46bd3d97: netperf.Throughput_tps  -11.3% regression Rik van Riel <riel@redhat.com> - 2017-09-14 18:00 +0200
          Re: [lkp-robot] [sched/fair] 6d46bd3d97: netperf.Throughput_tps  -11.3% regression Mike Galbraith <efault@gmx.de> - 2017-09-15 06:10 +0200
          Re: [lkp-robot] [sched/fair] 6d46bd3d97: netperf.Throughput_tps  -11.3% regression Joel Fernandes <joelaf@google.com> - 2017-09-17 08:50 +0200
            Re: [lkp-robot] [sched/fair] 6d46bd3d97: netperf.Throughput_tps  -11.3% regression Mike Galbraith <efault@gmx.de> - 2017-09-17 18:50 +0200
              Re: [lkp-robot] [sched/fair] 6d46bd3d97: netperf.Throughput_tps  -11.3% regression Joel Fernandes <joelaf@google.com> - 2017-09-17 23:50 +0200
                Re: [lkp-robot] [sched/fair] 6d46bd3d97: netperf.Throughput_tps  -11.3% regression Mike Galbraith <efault@gmx.de> - 2017-09-18 07:40 +0200
                  Re: [lkp-robot] [sched/fair] 6d46bd3d97: netperf.Throughput_tps  -11.3% regression Joel Fernandes <joelaf@google.com> - 2017-09-25 01:50 +0200

#1730016 — Re: [lkp-robot] [sched/fair] 6d46bd3d97: netperf.Throughput_tps -11.3% regression

FromJoel Fernandes <joelaf@google.com>
Date2017-09-10 19:00 +0200
SubjectRe: [lkp-robot] [sched/fair] 6d46bd3d97: netperf.Throughput_tps -11.3% regression
Message-ID<uodKq-6F7-15@gated-at.bofh.it>
Hi,

On Sun, Sep 10, 2017 at 6:40 AM, kernel test robot
<xiaolong.ye@intel.com> wrote:
>
> Greeting,
>
> FYI, we noticed a -11.3% regression of netperf.Throughput_tps due to commit:
>
>
> commit: 6d46bd3d9705555382b83554b56a34f231d5d1dd ("sched/fair: Improve the behavior of sync flag")
> url: https://github.com/0day-ci/linux/commits/Joel-Fernandes/sched-fair-Improve-the-behavior-of-sync-flag/20170829-191129
>

Glad to see the bot tested this RFC/RFT patch. Anyone know what in the
netperf test triggers use of the sync flag?

thanks,

-Joel


[..]

[toc] | [next] | [standalone]


#1730136

FromMike Galbraith <efault@gmx.de>
Date2017-09-11 05:00 +0200
Message-ID<uon73-4Ue-3@gated-at.bofh.it>
In reply to#1730016
On Sun, 2017-09-10 at 09:53 -0700, Joel Fernandes wrote:
> 
> Anyone know what in the netperf test triggers use of the sync flag?

homer:..kernel/linux-master # git grep wake_up_interruptible_sync_poll net
net/core/sock.c:                wake_up_interruptible_sync_poll(&wq->wait, POLLIN | POLLPRI |
net/core/sock.c:                        wake_up_interruptible_sync_poll(&wq->wait, POLLOUT |
net/sctp/socket.c:              wake_up_interruptible_sync_poll(&wq->wait, POLLIN |
net/smc/smc_rx.c:               wake_up_interruptible_sync_poll(&wq->wait, POLLIN | POLLPRI |
net/tipc/socket.c:              wake_up_interruptible_sync_poll(&wq->wait, POLLOUT |
net/tipc/socket.c:              wake_up_interruptible_sync_poll(&wq->wait, POLLIN |
net/unix/af_unix.c:                     wake_up_interruptible_sync_poll(&wq->wait,
net/unix/af_unix.c:             wake_up_interruptible_sync_poll(&u->peer_wait,

The same as metric tons of other stuff.

Once upon a time, we had avg_overlap to help decide whether to wake
core affine or not, on top of the wake_affine() imbalance constraint,
but instrumentation showed it to be too error prone, so it had to die.
 These days, an affine wakeup generally means cache affine, and the
sync hint gives you a wee bit more chance of migration near to tasty
hot data being approved.

The sync hint was born back in the bad old days, when communicating
tasks not sharing L2 may as well have been talking over two tin cans
and a limp string.  These days, things are oodles better, but truly
synchronous stuff could still benefit from core affinity (up to hugely
for very fast/light stuff) if it weren't for all the caveats that can
lead to tossing concurrency opportunities out the window.

	-Mike

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


#1730160

FromJoel Fernandes <joelaf@google.com>
Date2017-09-11 08:40 +0200
Message-ID<uoqxX-7vR-3@gated-at.bofh.it>
In reply to#1730136
Hi Mike,
Thanks a lot for sharing the history of this.

On Sun, Sep 10, 2017 at 7:55 PM, Mike Galbraith <efault@gmx.de> wrote:
> On Sun, 2017-09-10 at 09:53 -0700, Joel Fernandes wrote:
>>
>> Anyone know what in the netperf test triggers use of the sync flag?
>
> homer:..kernel/linux-master # git grep wake_up_interruptible_sync_poll net
> net/core/sock.c:                wake_up_interruptible_sync_poll(&wq->wait, POLLIN | POLLPRI |
> net/core/sock.c:                        wake_up_interruptible_sync_poll(&wq->wait, POLLOUT |
> net/sctp/socket.c:              wake_up_interruptible_sync_poll(&wq->wait, POLLIN |
> net/smc/smc_rx.c:               wake_up_interruptible_sync_poll(&wq->wait, POLLIN | POLLPRI |
> net/tipc/socket.c:              wake_up_interruptible_sync_poll(&wq->wait, POLLOUT |
> net/tipc/socket.c:              wake_up_interruptible_sync_poll(&wq->wait, POLLIN |
> net/unix/af_unix.c:                     wake_up_interruptible_sync_poll(&wq->wait,
> net/unix/af_unix.c:             wake_up_interruptible_sync_poll(&u->peer_wait,
>
> The same as metric tons of other stuff.
>
> Once upon a time, we had avg_overlap to help decide whether to wake
> core affine or not, on top of the wake_affine() imbalance constraint,
> but instrumentation showed it to be too error prone, so it had to die.
>  These days, an affine wakeup generally means cache affine, and the
> sync hint gives you a wee bit more chance of migration near to tasty
> hot data being approved.
>
> The sync hint was born back in the bad old days, when communicating
> tasks not sharing L2 may as well have been talking over two tin cans
> and a limp string.  These days, things are oodles better, but truly
> synchronous stuff could still benefit from core affinity (up to hugely
> for very fast/light stuff) if it weren't for all the caveats that can
> lead to tossing concurrency opportunities out the window.

Cool, thanks. For this test I suspect its the other way? I think the
reason why regresses is that the 'nr_running < 2' check is too weak of
a check to prevent sync in all bad situations ('bad' being pulling a
task to a crowded CPU). Could we maybe be having a situation for this
test where if the blocked load a CPU is high (many tasks recently were
running on it and went to sleep), then the nr_running < 2  is a false
positive and in such a scenario we listened to the sync flag when we
shouldn't have?

To make the load check more meaningful, I am thinking if using
wake_affine()'s balance check is a better thing to do than the
'nr_running < 2' check I used in this patch. Then again, since commit
3fed382b46baac ("sched/numa: Implement NUMA node level wake_affine()",
wake_affine() doesn't do balance check for CPUs within a socket so
probably bringing back something like the *old* wake_affine that
checked load between different CPUs within a socket is needed to avoid
a potentially disastrous sync decision?  The commit I refer to was
added with the reason that select_idle_sibling was selecting cores
anywhere within a socket, but with my patch we're more specifically
selecting the waker's CPU on passing the sync flag. Could you share
your thoughts about this?

I will run some tracing on this netperf test and try to understand the
undesirable behavior better as well,

thanks,

-Joel

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


#1730199

FromMike Galbraith <efault@gmx.de>
Date2017-09-11 10:10 +0200
Message-ID<uorX4-fL-17@gated-at.bofh.it>
In reply to#1730160
On Sun, 2017-09-10 at 23:32 -0700, Joel Fernandes wrote:
> Hi Mike,
> Thanks a lot for sharing the history of this.
> 
> On Sun, Sep 10, 2017 at 7:55 PM, Mike Galbraith <efault@gmx.de> wrote:
> > On Sun, 2017-09-10 at 09:53 -0700, Joel Fernandes wrote:
> >>
> >> Anyone know what in the netperf test triggers use of the sync flag?
> >
> > homer:..kernel/linux-master # git grep wake_up_interruptible_sync_poll net
> > net/core/sock.c:                wake_up_interruptible_sync_poll(&wq->wait, POLLIN | POLLPRI |
> > net/core/sock.c:                        wake_up_interruptible_sync_poll(&wq->wait, POLLOUT |
> > net/sctp/socket.c:              wake_up_interruptible_sync_poll(&wq->wait, POLLIN |
> > net/smc/smc_rx.c:               wake_up_interruptible_sync_poll(&wq->wait, POLLIN | POLLPRI |
> > net/tipc/socket.c:              wake_up_interruptible_sync_poll(&wq->wait, POLLOUT |
> > net/tipc/socket.c:              wake_up_interruptible_sync_poll(&wq->wait, POLLIN |
> > net/unix/af_unix.c:                     wake_up_interruptible_sync_poll(&wq->wait,
> > net/unix/af_unix.c:             wake_up_interruptible_sync_poll(&u->peer_wait,
> >
> > The same as metric tons of other stuff.
> >
> > Once upon a time, we had avg_overlap to help decide whether to wake
> > core affine or not, on top of the wake_affine() imbalance constraint,
> > but instrumentation showed it to be too error prone, so it had to die.
> >  These days, an affine wakeup generally means cache affine, and the
> > sync hint gives you a wee bit more chance of migration near to tasty
> > hot data being approved.
> >
> > The sync hint was born back in the bad old days, when communicating
> > tasks not sharing L2 may as well have been talking over two tin cans
> > and a limp string.  These days, things are oodles better, but truly
> > synchronous stuff could still benefit from core affinity (up to hugely
> > for very fast/light stuff) if it weren't for all the caveats that can
> > lead to tossing concurrency opportunities out the window.
> 
> Cool, thanks. For this test I suspect its the other way? I think the
> reason why regresses is that the 'nr_running < 2' check is too weak of
> a check to prevent sync in all bad situations ('bad' being pulling a
> task to a crowded CPU). Could we maybe be having a situation for this
> test where if the blocked load a CPU is high (many tasks recently were
> running on it and went to sleep), then the nr_running < 2  is a false
> positive and in such a scenario we listened to the sync flag when we
> shouldn't have?

nr_running has ~little to do with synchronous baton passing, or rather
with overlap being too small to overcome costs (L2 miss/cstate..).  If
you run TCP_RR, pipe-test or ilk (tiny ball ping-pong), you should see
gorgeous numbers, and may find yourself thinking sync is a wonder
elixir for network-land, but 'taint necessarily so in the real world.

The only way to win the "Rob Peter to pay Paul" game is through the use
of knowledge, acquisition of which is expensive.  Try resurrecting the
cheap avg_overlap, you'll love it.. for a little while.

> To make the load check more meaningful, I am thinking if using
> wake_affine()'s balance check is a better thing to do than the
> 'nr_running < 2' check I used in this patch. Then again, since commit
> 3fed382b46baac ("sched/numa: Implement NUMA node level wake_affine()",
> wake_affine() doesn't do balance check for CPUs within a socket so
> probably bringing back something like the *old* wake_affine that
> checked load between different CPUs within a socket is needed to avoid
> a potentially disastrous sync decision?  The commit I refer to was
> added with the reason that select_idle_sibling was selecting cores
> anywhere within a socket, but with my patch we're more specifically
> selecting the waker's CPU on passing the sync flag. Could you share
> your thoughts about this?

Mucking about with wake_affine() in core affinity context would be a
step backward methinks.  The sync hint has not meant CPU affine for
quite some time now.

If you can come up with a sync hint modification that is win/win,
super, but I suspect you'll find it a lot easier to create a new
'really really' flag or make your governor more responsive.

	-Mike

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


#1732371

FromRik van Riel <riel@redhat.com>
Date2017-09-14 18:00 +0200
Message-ID<upEIy-6V9-27@gated-at.bofh.it>
In reply to#1730160

[Multipart message — attachments visible in raw view] — view raw

On Sun, 2017-09-10 at 23:32 -0700, Joel Fernandes wrote:
> 
> To make the load check more meaningful, I am thinking if using
> wake_affine()'s balance check is a better thing to do than the
> 'nr_running < 2' check I used in this patch. Then again, since commit
> 3fed382b46baac ("sched/numa: Implement NUMA node level
> wake_affine()",
> wake_affine() doesn't do balance check for CPUs within a socket so
> probably bringing back something like the *old* wake_affine that
> checked load between different CPUs within a socket is needed to
> avoid
> a potentially disastrous sync decision? 

This is because regardless of whether or not we did
an affine wakeup, the code called select_idle_sibling
within that socket, anyway.

In other words, the behavior for within-socket
wakeups was not substantially different with or
without an affine wakeup.

All that changed is which CPU select_idle_sibling
starts searching at, and that only if the woken
task's previous CPU is not idle.

>  The commit I refer to was
> added with the reason that select_idle_sibling was selecting cores
> anywhere within a socket, but with my patch we're more specifically
> selecting the waker's CPU on passing the sync flag. Could you share
> your thoughts about this?

On systems with SMT, it may make more sense for
sync wakeups to look for idle threads of the same
core, than to have the woken task end up on the 
same thread, and wait for the current task to stop
running.

"Strong sync" wakeups like you propose would also
change the semantics of wake_wide() and potentially
other bits of code...

-- 
All rights reversed

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


#1732703

FromMike Galbraith <efault@gmx.de>
Date2017-09-15 06:10 +0200
Message-ID<upQ6Z-67k-3@gated-at.bofh.it>
In reply to#1732371
On Thu, 2017-09-14 at 11:56 -0400, Rik van Riel wrote:
> 
> On systems with SMT, it may make more sense for
> sync wakeups to look for idle threads of the same
> core, than to have the woken task end up on the 
> same thread, and wait for the current task to stop
> running.

Depends.

homer:/root # taskset -c 3 pipe-test
1.412185 usecs/loop -- avg 1.412185 1416.2 KHz
homer:/root # taskset -c 2,3 pipe-test
2.298820 usecs/loop -- avg 2.298820 870.0 KHz
homer:/root # taskset -c 3,7 pipe-test
1.899164 usecs/loop -- avg 1.899164 1053.1 KHz

For pipe-test, having ~zero overlap as well as ~zero footprint, that's
a good choice, but..

homer:/root # taskset -c 3 tbench.sh 1 10 2>&1|grep Throughput
Throughput 844.04 MB/sec  1 clients  1 procs  max_latency=0.042 ms
homer:/root # taskset -c 2,3 tbench.sh 1 10 2>&1|grep Throughput
Throughput 713.25 MB/sec  1 clients  1 procs  max_latency=0.324 ms
homer:/root # taskset -c 3,7 tbench.sh 1 10 2>&1|grep Throughput
Throughput 512.866 MB/sec  1 clients  1 procs  max_latency=0.454 ms

..for tbench, where my crusty ole Q6600 turns in a win by scheduling
the pair on separate L2 sharing cores, for the more modern SMT equipped
i4790, targeting shared L2 is the worst choice.

Bigger issue is that while microbenchmark behavior is consistant,
applications tend to process data and react to it (vs merely batting it
about like playful kittens, cute, but not all that productive), likely
mucking up any heuristic anyone invents with depressing regularity.

	-Mike

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


#1733397

FromJoel Fernandes <joelaf@google.com>
Date2017-09-17 08:50 +0200
Message-ID<uqByV-4pk-1@gated-at.bofh.it>
In reply to#1732371
Hi Rik,

On Thu, Sep 14, 2017 at 8:56 AM, Rik van Riel <riel@redhat.com> wrote:
> On Sun, 2017-09-10 at 23:32 -0700, Joel Fernandes wrote:
>>
>> To make the load check more meaningful, I am thinking if using
>> wake_affine()'s balance check is a better thing to do than the
>> 'nr_running < 2' check I used in this patch. Then again, since commit
>> 3fed382b46baac ("sched/numa: Implement NUMA node level
>> wake_affine()",
>> wake_affine() doesn't do balance check for CPUs within a socket so
>> probably bringing back something like the *old* wake_affine that
>> checked load between different CPUs within a socket is needed to
>> avoid
>> a potentially disastrous sync decision?
>
> This is because regardless of whether or not we did
> an affine wakeup, the code called select_idle_sibling
> within that socket, anyway.
>
> In other words, the behavior for within-socket
> wakeups was not substantially different with or
> without an affine wakeup.
>
> All that changed is which CPU select_idle_sibling
> starts searching at, and that only if the woken
> task's previous CPU is not idle.

Yes I understand. However with my 'strong sync' patch, such a
balancing check could be useful which is what I was trying to do in a
different way in my patch - but it could be that my way is not good
enough and potentially the old wake_affine check could help here - I
thought of spending some time next week after LPC travel to
reintroduce the old wake_affine and monitor this signal with some
tracing for the regressing netperf usecase.

>>  The commit I refer to was
>> added with the reason that select_idle_sibling was selecting cores
>> anywhere within a socket, but with my patch we're more specifically
>> selecting the waker's CPU on passing the sync flag. Could you share
>> your thoughts about this?
>
> On systems with SMT, it may make more sense for
> sync wakeups to look for idle threads of the same
> core, than to have the woken task end up on the
> same thread, and wait for the current task to stop
> running.

I am ok with additionally doing an select_idle_smt for the SMT cases.
However Mike shows that it doesn't necessarily cause a performance
improvement. But if there is consensus on checking for idle SMT
threads, then I'm Ok with doing that.

>
> "Strong sync" wakeups like you propose would also
> change the semantics of wake_wide() and potentially
> other bits of code...
>

I understand, I am not very confident that wake_wide does the right
thing anyway. Atleast for Android, wake_wide doesn't seem to mirror
the most common usecase of display pipeline well. It seems that we
have cases where the 'flip count' is really high and causes wake_wide
all the time and sends us straight to the wake up slow path causing
regressions in Android benchmarks.

Atleast with the sync flag, the caller provides a meaningful
indication and I think making that flag stronger / more preferred than
wake_wide makes sense from that perspective since its not a signal
that's guessed, but is rather an input request.

thanks,

-Joel

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


#1733493

FromMike Galbraith <efault@gmx.de>
Date2017-09-17 18:50 +0200
Message-ID<uqKVz-216-3@gated-at.bofh.it>
In reply to#1733397
On Sat, 2017-09-16 at 23:42 -0700, Joel Fernandes wrote:
> 
> Yes I understand. However with my 'strong sync' patch, such a
> balancing check could be useful which is what I was trying to do in a
> different way in my patch - but it could be that my way is not good
> enough and potentially the old wake_affine check could help here

Help how?  The old wake_affine() check contained zero concurrency
information, it served to exclude excessive stacking, defeating the
purpose of SMP.  A truly synchronous wakeup has absolutely nothing to
do with load balance in the general case: you can neither generate nor
cure an imbalance by replacing one (nice zero) task with another.  The
mere existence of a load based braking mechanism speaks volumes.

> On systems with SMT, it may make more sense for
> > sync wakeups to look for idle threads of the same
> > core, than to have the woken task end up on the
> > same thread, and wait for the current task to stop
> > running.
> 
> I am ok with additionally doing an select_idle_smt for the SMT cases.
> However Mike shows that it doesn't necessarily cause a performance
> improvement. But if there is consensus on checking for idle SMT
> threads, then I'm Ok with doing that.

select_idle_sibling() used to check thread first, that was changed to
core first for performance reasons.

> > "Strong sync" wakeups like you propose would also
> > change the semantics of wake_wide() and potentially
> > other bits of code...
> >
> 
> I understand, I am not very confident that wake_wide does the right
> thing anyway. Atleast for Android, wake_wide doesn't seem to mirror
> the most common usecase of display pipeline well. It seems that we
> have cases where the 'flip count' is really high and causes wake_wide
> all the time and sends us straight to the wake up slow path causing
> regressions in Android benchmarks.

Hm.  It didn't pull those counts out of the vacuum, it measured them.
 It definitely does not force Android into the full balance path, that
is being done by Android developers, as SD_BALANCE_WAKE is off by
default.  It was briefly on by default, but was quickly turned back off
because it... induced performance regressions.

In any case, if you have cause to believe that wake_wide() is causing
you grief, why the heck are you bending up the sync hint?

> Atleast with the sync flag, the caller provides a meaningful
> indication and I think making that flag stronger / more preferred than
> wake_wide makes sense from that perspective since its not a signal
> that's guessed, but is rather an input request.

Sort of, if you disregard the history I mentioned...

https://www.youtube.com/watch?v=Yho1Eydh1mM :)

Lacking solid concurrency information to base your decision on, you'll
end up robbing Peter to pay Paul forever, you absolutely will stack
non-synchronous tasks, inducing needless latency hits and injuring
scalability.  We've been down that road.  $subject was a very small
sample of what lies down this path <bang bang bang>.

	-Mike

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


#1733541

FromJoel Fernandes <joelaf@google.com>
Date2017-09-17 23:50 +0200
Message-ID<uqPBT-5hg-9@gated-at.bofh.it>
In reply to#1733493
Hi Mike,

On Sun, Sep 17, 2017 at 9:47 AM, Mike Galbraith <efault@gmx.de> wrote:
> On Sat, 2017-09-16 at 23:42 -0700, Joel Fernandes wrote:
>>
>> Yes I understand. However with my 'strong sync' patch, such a
>> balancing check could be useful which is what I was trying to do in a
>> different way in my patch - but it could be that my way is not good
>> enough and potentially the old wake_affine check could help here
>
> Help how?  The old wake_affine() check contained zero concurrency
> information, it served to exclude excessive stacking, defeating the
> purpose of SMP.  A truly synchronous wakeup has absolutely nothing to
> do with load balance in the general case: you can neither generate nor
> cure an imbalance by replacing one (nice zero) task with another.  The
> mere existence of a load based braking mechanism speaks volumes.

This is the part I didn't get.. you said "neither generate an
imbalance", it is possible that a CPU with a high blocked load but
just happen to be running 1 task at the time and did a sync wake up
for another task. In this case dragging the task onto the waker's CPU
might hurt it since it will face more competition than if it were
woken up on its previous CPU which is possibly lighty loaded than the
waker's CPU?

Also the other thing I didn't fully get is why is concurrency a
discussion point here, in this case A wakes up B and goes to sleep,
and then B wakes up A. They never run concurrently. Could you let me
know what I am missing?

>> On systems with SMT, it may make more sense for
>> > sync wakeups to look for idle threads of the same
>> > core, than to have the woken task end up on the
>> > same thread, and wait for the current task to stop
>> > running.
>>
>> I am ok with additionally doing an select_idle_smt for the SMT cases.
>> However Mike shows that it doesn't necessarily cause a performance
>> improvement. But if there is consensus on checking for idle SMT
>> threads, then I'm Ok with doing that.
>
> select_idle_sibling() used to check thread first, that was changed to
> core first for performance reasons.

Oh I see. Ok.

>> > "Strong sync" wakeups like you propose would also
>> > change the semantics of wake_wide() and potentially
>> > other bits of code...
>> >
>>
>> I understand, I am not very confident that wake_wide does the right
>> thing anyway. Atleast for Android, wake_wide doesn't seem to mirror
>> the most common usecase of display pipeline well. It seems that we
>> have cases where the 'flip count' is really high and causes wake_wide
>> all the time and sends us straight to the wake up slow path causing
>> regressions in Android benchmarks.
>
> Hm.  It didn't pull those counts out of the vacuum, it measured them.
>  It definitely does not force Android into the full balance path, that
> is being done by Android developers, as SD_BALANCE_WAKE is off by
> default.  It was briefly on by default, but was quickly turned back off
> because it... induced performance regressions.
>
> In any case, if you have cause to believe that wake_wide() is causing
> you grief, why the heck are you bending up the sync hint?

So its not just wake_wide causing the grief, even select_idle_sibling
doesn't seem to be doing the right thing. We really don't want to wake
up a task on an idle CPU if the current CPU is a better candidate.
Binder microbenchmarks should that (as you can see in the results in
this patch) it performs better to wake up on the current CPU (no wake
up from idle latency on a sibling etc). Perhaps we should fix
select_idle_sibling to also consider latency of CPU to come out of
idle? Using the sync hint was/is a way on the product kernel to
prevent both these paths. On current products, sync is ignored though
if the system is in an "overutilized" state (any of the CPUs are more
than 80% utilized) but otherwise the sync is used as a hard flag. This
is all probably wrong though - considering the concurrency point you
brought up..

>> Atleast with the sync flag, the caller provides a meaningful
>> indication and I think making that flag stronger / more preferred than
>> wake_wide makes sense from that perspective since its not a signal
>> that's guessed, but is rather an input request.
>
> Sort of, if you disregard the history I mentioned...
>
> https://www.youtube.com/watch?v=Yho1Eydh1mM :)

No no, definitely not disregarding anything :) - just trying to make
sense of it all (and the history). Thanks so much for sharing it and
all the current/previous discussion.

>
> Lacking solid concurrency information to base your decision on, you'll
> end up robbing Peter to pay Paul forever, you absolutely will stack
> non-synchronous tasks, inducing needless latency hits and injuring
> scalability.  We've been down that road.  $subject was a very small
> sample of what lies down this path <bang bang bang>.

Ok. That is pretty scary. I am going to spend some time first go
through all the previous emails in this and other threads on the
balance flag usages and try to work on a solution after that. I will
probably start to document somewhere all the usecases for my own
sanity :)

thanks,

- Joel

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


#1733647

FromMike Galbraith <efault@gmx.de>
Date2017-09-18 07:40 +0200
Message-ID<uqWWJ-1AY-11@gated-at.bofh.it>
In reply to#1733541
On Sun, 2017-09-17 at 14:41 -0700, Joel Fernandes wrote:
> Hi Mike,
> 
> On Sun, Sep 17, 2017 at 9:47 AM, Mike Galbraith <efault@gmx.de> wrote:
> > On Sat, 2017-09-16 at 23:42 -0700, Joel Fernandes wrote:
> >>
> >> Yes I understand. However with my 'strong sync' patch, such a
> >> balancing check could be useful which is what I was trying to do in a
> >> different way in my patch - but it could be that my way is not good
> >> enough and potentially the old wake_affine check could help here
> >
> > Help how?  The old wake_affine() check contained zero concurrency
> > information, it served to exclude excessive stacking, defeating the
> > purpose of SMP.  A truly synchronous wakeup has absolutely nothing to
> > do with load balance in the general case: you can neither generate nor
> > cure an imbalance by replacing one (nice zero) task with another.  The
> > mere existence of a load based braking mechanism speaks volumes.
> 
> This is the part I didn't get.. you said "neither generate an
> imbalance", it is possible that a CPU with a high blocked load but
> just happen to be running 1 task at the time and did a sync wake up
> for another task. In this case dragging the task onto the waker's CPU
> might hurt it since it will face more competition than if it were
> woken up on its previous CPU which is possibly lighty loaded than the
> waker's CPU?

Sure, a preexisting imbalance, but what does that have to do with
generic pass the baton behavior, and knowing whether pull will result
in a performance win or loss?  In the overloaded and imbalanced case, a
lower load number on this/that CPU means little in and of itself wrt
latency expectations... the wakee may or may not be next in line, may
or may not be able to cut the line (preempt).

> Also the other thing I didn't fully get is why is concurrency a
> discussion point here, in this case A wakes up B and goes to sleep,
> and then B wakes up A. They never run concurrently. Could you let me
> know what I am missing?

If waker does not IMMEDIATELY sleep, and you wake CPU affine, you toss
the time interval between wakeup and context switch out the window, the
wakee could have already been executing elsewhere when the waker gets
around to getting the hell out of the way.

The point I'm belaboring here is that we had that load check and more,
and it proved insufficient.  Yeah, pipe-test absolutely loves running
on one CPU, but who cares, pipe-test is an overhead measurement tool,
NOT a benchmark, those try to emulate the real world.

Hell, take two large footprint tasks, and let them exchange data
briefly via pipe.. what would make it a wonderful idea to pull these
tasks together each and every time they did that?  Because pipe-test
can thus play super fast ping-pong with itself?  Obviously not.

> >> On systems with SMT, it may make more sense for
> >> > sync wakeups to look for idle threads of the same
> >> > core, than to have the woken task end up on the
> >> > same thread, and wait for the current task to stop
> >> > running.
> >>
> >> I am ok with additionally doing an select_idle_smt for the SMT cases.
> >> However Mike shows that it doesn't necessarily cause a performance
> >> improvement. But if there is consensus on checking for idle SMT
> >> threads, then I'm Ok with doing that.
> >
> > select_idle_sibling() used to check thread first, that was changed to
> > core first for performance reasons.
> 
> Oh I see. Ok.
> 
> >> > "Strong sync" wakeups like you propose would also
> >> > change the semantics of wake_wide() and potentially
> >> > other bits of code...
> >> >
> >>
> >> I understand, I am not very confident that wake_wide does the right
> >> thing anyway. Atleast for Android, wake_wide doesn't seem to mirror
> >> the most common usecase of display pipeline well. It seems that we
> >> have cases where the 'flip count' is really high and causes wake_wide
> >> all the time and sends us straight to the wake up slow path causing
> >> regressions in Android benchmarks.
> >
> > Hm.  It didn't pull those counts out of the vacuum, it measured them.
> >  It definitely does not force Android into the full balance path, that
> > is being done by Android developers, as SD_BALANCE_WAKE is off by
> > default.  It was briefly on by default, but was quickly turned back off
> > because it... induced performance regressions.
> >
> > In any case, if you have cause to believe that wake_wide() is causing
> > you grief, why the heck are you bending up the sync hint?
> 
> So its not just wake_wide causing the grief, even select_idle_sibling
> doesn't seem to be doing the right thing. We really don't want to wake
> up a task on an idle CPU if the current CPU is a better candidate.

That is the nut, defining better candidate is not so trivial.  Lacking
concrete knowledge (omniscience?), you're always gambling, betting on
concurrency potential existing is much safer than betting against it if
your prime directive is to maximize utilization.

> Binder microbenchmarks should that (as you can see in the results in
> this patch) it performs better to wake up on the current CPU (no wake
> up from idle latency on a sibling etc). Perhaps we should fix
> select_idle_sibling to also consider latency of CPU to come out of
> idle?

That would add complexity.  If you're gonna do that, you may as well go
the extra mile, nuke it, and unify the full balance path instead.

>  Using the sync hint was/is a way on the product kernel to
> prevent both these paths. On current products, sync is ignored though
> if the system is in an "overutilized" state (any of the CPUs are more
> than 80% utilized) but otherwise the sync is used as a hard flag. This
> is all probably wrong though - considering the concurrency point you
> brought up..

My experience with this space was that it's remarkably easy to wreck
performance, why I was inspired to bang on podium with shoe.  I'm not
trying to discourage your explorations, merely passing along a well
meant "Danger Will Robinson".

	-Mike

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


#1738593

FromJoel Fernandes <joelaf@google.com>
Date2017-09-25 01:50 +0200
Message-ID<utoOR-6Hv-3@gated-at.bofh.it>
In reply to#1733647
Hi Mike,

On Sun, Sep 17, 2017 at 10:30 PM, Mike Galbraith <efault@gmx.de> wrote:
> On Sun, 2017-09-17 at 14:41 -0700, Joel Fernandes wrote:
>> Hi Mike,
>>
>> On Sun, Sep 17, 2017 at 9:47 AM, Mike Galbraith <efault@gmx.de> wrote:
>> > On Sat, 2017-09-16 at 23:42 -0700, Joel Fernandes wrote:
>> >>
>> >> Yes I understand. However with my 'strong sync' patch, such a
>> >> balancing check could be useful which is what I was trying to do in a
>> >> different way in my patch - but it could be that my way is not good
>> >> enough and potentially the old wake_affine check could help here
>> >
>> > Help how?  The old wake_affine() check contained zero concurrency
>> > information, it served to exclude excessive stacking, defeating the
>> > purpose of SMP.  A truly synchronous wakeup has absolutely nothing to
>> > do with load balance in the general case: you can neither generate nor
>> > cure an imbalance by replacing one (nice zero) task with another.  The
>> > mere existence of a load based braking mechanism speaks volumes.
>>
>> This is the part I didn't get.. you said "neither generate an
>> imbalance", it is possible that a CPU with a high blocked load but
>> just happen to be running 1 task at the time and did a sync wake up
>> for another task. In this case dragging the task onto the waker's CPU
>> might hurt it since it will face more competition than if it were
>> woken up on its previous CPU which is possibly lighty loaded than the
>> waker's CPU?
>
> Sure, a preexisting imbalance, but what does that have to do with
> generic pass the baton behavior, and knowing whether pull will result
> in a performance win or loss?  In the overloaded and imbalanced case, a
> lower load number on this/that CPU means little in and of itself wrt
> latency expectations... the wakee may or may not be next in line, may
> or may not be able to cut the line (preempt).

In my patch, I used nr_running == 1, so if waker slept immediately,
then wakee would be next in line. I guess this is the part I
misunderstood - that I assumed for all cases the sync waker sleeps
immediately, even though it does in the binder use cases. We have
control over the binder userspace bits that sleep immediately since
its part of the framework - user apps don't decide whether to stay
awake or not - the framework will put them to sleep since any progress
can happen only after waiting for the transaction to return. However
this assumption may not be true for other users of the regular sync
flag as you pointed :-/.

Just for completeness sake, I wanted to mention how we have a patch
similar to this on the Pixel product and works real well for all the
usecases we care about:
https://android.googlesource.com/kernel/msm.git/+/android-msm-marlin-3.18-oreo-r6/kernel/sched/fair.c#5678
It will probably not work well if someone tried to run netperf or
other usecases where waker doesn't sleep immediately and is definitely
not mainlinable considering the wreckage in $SUBJECT.

>
>> Also the other thing I didn't fully get is why is concurrency a
>> discussion point here, in this case A wakes up B and goes to sleep,
>> and then B wakes up A. They never run concurrently. Could you let me
>> know what I am missing?
>
> If waker does not IMMEDIATELY sleep, and you wake CPU affine, you toss
> the time interval between wakeup and context switch out the window, the
> wakee could have already been executing elsewhere when the waker gets
> around to getting the hell out of the way.
>
> The point I'm belaboring here is that we had that load check and more,
> and it proved insufficient.  Yeah, pipe-test absolutely loves running
> on one CPU, but who cares, pipe-test is an overhead measurement tool,
> NOT a benchmark, those try to emulate the real world.

Ok.

> Hell, take two large footprint tasks, and let them exchange data
> briefly via pipe.. what would make it a wonderful idea to pull these
> tasks together each and every time they did that?  Because pipe-test
> can thus play super fast ping-pong with itself?  Obviously not.

Yes, I agree with you.

[..]
>>
>> >> > "Strong sync" wakeups like you propose would also
>> >> > change the semantics of wake_wide() and potentially
>> >> > other bits of code...doesn't make much sense for
>> >> >
>> >>
>> >> I understand, I am not very confident that wake_wide does the right
>> >> thing anyway. Atleast for Android, wake_wide doesn't seem to mirror
>> >> the most common usecase of display pipeline well. It seems that we
>> >> have cases where the 'flip count' is really high and causes wake_wide
>> >> all the time and sends us straight to the wake up slow path causing
>> >> regressions in Android benchmarks.
>> >
>> > Hm.  It didn't pull those counts out of the vacuum, it measured them.
>> >  It definitely does not force Android into the full balance path, that
>> > is being done by Android developers, as SD_BALANCE_WAKE is off by
>> > default.  It was briefly on by default, but was quickly turned back off
>> > because it... induced performance regressions.
>> >
>> > In any case, if you have cause to believe that wake_wide() is causing
>> > you grief, why the heck are you bending up the sync hint?
>>
>> So its not just wake_wide causing the grief, even select_idle_sibling
>> doesn't seem to be doing the right thing. We really don't want to wake
>> up a task on an idle CPU if the current CPU is a better candidate.
>
> That is the nut, defining better candidate is not so trivial.  Lacking
> concrete knowledge (omniscience?), you're always gambling, betting on
> concurrency potential existing is much safer than betting against it if
> your prime directive is to maximize utilization.

Ok so I think then reusing the sync flag for binder in mainline
doesn't make much sense and we could define a new flag that indicates
the waker will sleep immediately and call it WF_HSYNC (as in hard
sync) - since in the binder case we have this knowledge that waker is
going to sleep waiting for the transaction to finish.. I think the
mistake I did was trying to change the semantic of the original sync
flag which cannot assume that the waker sleeps immediately.

>> Binder microbenchmarks should that (as you can see in the results in
>> this patch) it performs better to wake up on the current CPU (no wake
>> up from idle latency on a sibling etc). Perhaps we should fix
>> select_idle_sibling to also consider latency of CPU to come out of
>> idle?
>
> That would add complexity.  If you're gonna do that, you may as well go
> the extra mile, nuke it, and unify the full balance path instead.

Ok, I agree its not a good idea to make the fast path any slower just for this.

>>  Using the sync hint was/is a way on the product kernel to
>> prevent both these paths. On current products, sync is ignored though
>> if the system is in an "overutilized" state (any of the CPUs are more
>> than 80% utilized) but otherwise the sync is used as a hard flag. This
>> is all probably wrong though - considering the concurrency point you
>> brought up..
>
> My experience with this space was that it's remarkably easy to wreck
> performance, why I was inspired to bang on podium with shoe.  I'm not
> trying to discourage your explorations, merely passing along a well
> meant "Danger Will Robinson".

Thanks for the guidance, and sharing your knowledge/experience about this,

regards,

- Joel

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web