From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
To: Waiman Long <waiman.long@hp.com>
Cc: linux-kernel@vger.kernel.org, mingo@elte.hu,
laijs@cn.fujitsu.com, dipankar@in.ibm.com,
akpm@linux-foundation.org, mathieu.desnoyers@efficios.com,
josh@joshtriplett.org, niv@us.ibm.com, tglx@linutronix.de,
peterz@infradead.org, rostedt@goodmis.org,
Valdis.Kletnieks@vt.edu, dhowells@redhat.com,
edumazet@google.com, darren@dvhart.com, fweisbec@gmail.com,
sbw@mit.edu, torvalds@linux-foundation.org
Subject: Re: [PATCH RFC ticketlock] Auto-queued ticketlock
Date: Tue, 11 Jun 2013 09:36:07 -0700 [thread overview]
Message-ID: <20130611163607.GG5146@linux.vnet.ibm.com> (raw)
In-Reply-To: <51B748DA.2070306@hp.com>
On Tue, Jun 11, 2013 at 11:57:14AM -0400, Waiman Long wrote:
> On 06/09/2013 03:36 PM, Paul E. McKenney wrote:
> >Breaking up locks is better than implementing high-contention locks, but
> >if we must have high-contention locks, why not make them automatically
> >switch between light-weight ticket locks at low contention and queued
> >locks at high contention?
> >
> >This commit therefore allows ticket locks to automatically switch between
> >pure ticketlock and queued-lock operation as needed. If too many CPUs
> >are spinning on a given ticket lock, a queue structure will be allocated
> >and the lock will switch to queued-lock operation. When the lock becomes
> >free, it will switch back into ticketlock operation. The low-order bit
> >of the head counter is used to indicate that the lock is in queued mode,
> >which forces an unconditional mismatch between the head and tail counters.
> >This approach means that the common-case code path under conditions of
> >low contention is very nearly that of a plain ticket lock.
> >
> >A fixed number of queueing structures is statically allocated in an
> >array. The ticket-lock address is used to hash into an initial element,
> >but if that element is already in use, it moves to the next element. If
> >the entire array is already in use, continue to spin in ticket mode.
> >
> >This has been only lightly tested in the kernel, though a userspace
> >implementation has survived substantial testing.
> >
> >Signed-off-by: Paul E. McKenney<paulmck@linux.vnet.ibm.com>
>
> This is an interesting patch and I think it is useful for workloads
> that run on systems with a large number of CPUs.
>
> >diff --git a/arch/x86/include/asm/spinlock_types.h b/arch/x86/include/asm/spinlock_types.h
> >index ad0ad07..cdaefdd 100644
> >--- a/arch/x86/include/asm/spinlock_types.h
> >+++ b/arch/x86/include/asm/spinlock_types.h
> >@@ -7,12 +7,18 @@
> >
> > #include<linux/types.h>
> >
> >-#if (CONFIG_NR_CPUS< 256)
> >+#if (CONFIG_NR_CPUS< 128)
> > typedef u8 __ticket_t;
> > typedef u16 __ticketpair_t;
> >-#else
> >+#define TICKET_T_CMP_GE(a, b) (UCHAR_MAX / 2>= (unsigned char)((a) - (b)))
> >+#elif (CONFIG_NR_CPUS< 32768)
> > typedef u16 __ticket_t;
> > typedef u32 __ticketpair_t;
> >+#define TICKET_T_CMP_GE(a, b) (USHRT_MAX / 2>= (unsigned short)((a) - (b)))
> >+#else
> >+typedef u32 __ticket_t;
> >+typedef u64 __ticketpair_t;
> >+#define TICKET_T_CMP_GE(a, b) (UINT_MAX / 2>= (unsigned int)((a) - (b)))
> > #endif
>
> It is theoretically possible that a large number of CPUs (says 64 or
> more with CONFIG_NR_CPUS < 128) can acquire a ticket from the lock
> before the check for TICKET_T_CMP_GE() in tkt_spin_pass(). So the
> check will fail even when there is a large number of CPUs contending
> for the lock. The chance of this happening is, of course, extremely
> rare. This is not an error as the lock is still working as it should
> be without your change.
Good point, I need to change the limits from 128 and 32768 to 64 and 16384
in order to guarantee that the comparison will work correctly. Done.
> >+/*
> >+ * TKT_Q_SWITCH is twice the number of CPUs that must be spinning on a
> >+ * given ticket lock to motivate switching to spinning on a queue.
> >+ * The reason that it is twice the number is because the bottom bit of
> >+ * the ticket is reserved for the bit that indicates that a queue is
> >+ * associated with the lock.
> >+ */
> >+#define TKT_Q_SWITCH (16 * 2)
> >+
> >+/*
> >+ * TKT_Q_NQUEUES is the number of queues to maintain. Large systems
> >+ * might have multiple highly contended locks, so provide more queues for
> >+ * systems with larger numbers of CPUs.
> >+ */
> >+#define TKT_Q_NQUEUES (DIV_ROUND_UP(NR_CPUS + TKT_Q_SWITCH - 1, TKT_Q_SWITCH) * 2)
> >+
> >+/* The queues themselves. */
> >+struct tkt_q_head tkt_q_heads[TKT_Q_NQUEUES];
>
> I am a bit concern about the size of the head queue table itself.
> RHEL6, for example, had defined CONFIG_NR_CPUS to be 4096 which mean
> a table size of 256. Maybe it is better to dynamically allocate the
> table at init time depending on the actual number of CPUs in the
> system.
But if your kernel is built for 4096 CPUs, the 32*256=8192 bytes of memory
is way down in the noise. Systems that care about that small an amount
of memory probably have a small enough number of CPUs that they can just
turn off queueing at build time using CONFIG_TICKET_LOCK_QUEUED=n, right?
> >+/*
> >+ * Return a pointer to the queue header associated with the specified lock,
> >+ * or return NULL if there is no queue for the lock or if the lock's queue
> >+ * is in transition.
> >+ */
> >+static struct tkt_q_head *tkt_q_find_head(arch_spinlock_t *asp)
> >+{
> >+ int i;
> >+ int start;
> >+
> >+ start = i = tkt_q_hash(asp);
> >+ do
> >+ if (tkt_q_heads[i].ref == asp)
> >+ return&tkt_q_heads[i];
> >+ while ((i = tkt_q_next_slot(i)) != start);
> >+ return NULL;
> >+}
>
> With a table size of 256 and you have to scan the whole table to
> find the right head queue. This can be a significant overhead. I
> will suggest setting a limiting of how many entries it scans before
> it aborts rather than checking the whole table.
But it will scan 256 entries only if there are 256 other locks in queued
mode, which is -very- unlikely, even given 4096 CPUs. That said, if you
show me that this results in a real latency problem on a real system,
I would be happy to provide a way to limit the search.
> >+/*
> >+ * Hand the lock off to the first CPU on the queue.
> >+ */
> >+void tkt_q_do_wake(arch_spinlock_t *asp)
> >+{
> >+ struct tkt_q_head *tqhp;
> >+ struct tkt_q *tqp;
> >+
> >+ /* If the queue is still being set up, wait for it. */
> >+ while ((tqhp = tkt_q_find_head(asp)) == NULL)
> >+ cpu_relax();
> >+
> >+ for (;;) {
> >+
> >+ /* Find the first queue element. */
> >+ tqp = ACCESS_ONCE(tqhp->spin);
> >+ if (tqp != NULL)
> >+ break; /* Element exists, hand off lock. */
> >+ if (tkt_q_try_unqueue(asp, tqhp))
> >+ return; /* No element, successfully removed queue. */
> >+ cpu_relax();
> >+ }
> >+ if (ACCESS_ONCE(tqhp->head_tkt) != -1)
> >+ ACCESS_ONCE(tqhp->head_tkt) = -1;
>
> In case NR_CPUS is 32768 or higher, the ticket will be of type u32
> and tqhp->head_tkt is s32. So -1 will be a valid ticket number. You
> may have to conditionally define head_tkt to be s64 when the ticket
> is u32.
Good catch! For the moment, I just made head_tkt unconditionally s64.
I bet that the extra comparison work has no system-visible effect. ;-)
> Do you have any data on how much this patch can actually improve
> performance on certain workloads? This will help the discussion
> here.
I could post some microbenchmark numbers if that would help.
Thanx, Paul
next prev parent reply other threads:[~2013-06-11 16:43 UTC|newest]
Thread overview: 96+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-06-09 19:36 Paul E. McKenney
2013-06-10 20:47 ` Steven Rostedt
2013-06-10 20:57 ` Paul E. McKenney
2013-06-10 21:01 ` Thomas Gleixner
2013-06-10 21:15 ` Paul E. McKenney
2013-06-10 21:08 ` Steven Rostedt
2013-06-10 21:30 ` Paul E. McKenney
2013-06-10 21:35 ` Eric Dumazet
2013-06-10 21:54 ` Paul E. McKenney
2013-06-10 23:02 ` Steven Rostedt
2013-06-11 0:22 ` Paul E. McKenney
2013-06-11 0:44 ` Steven Rostedt
2013-06-11 0:51 ` Linus Torvalds
2013-06-11 7:53 ` Lai Jiangshan
2013-06-11 10:14 ` Paul E. McKenney
2013-06-11 15:22 ` Steven Rostedt
2013-06-11 16:45 ` Paul E. McKenney
2013-06-11 10:06 ` Paul E. McKenney
2013-06-11 17:53 ` Davidlohr Bueso
2013-06-11 18:05 ` Paul E. McKenney
2013-06-11 18:10 ` Steven Rostedt
2013-06-11 18:14 ` Davidlohr Bueso
2013-06-11 18:46 ` Paul E. McKenney
2013-06-12 17:50 ` Davidlohr Bueso
2013-06-12 18:15 ` Linus Torvalds
2013-06-12 20:03 ` Davidlohr Bueso
2013-06-12 20:26 ` Linus Torvalds
2013-06-12 20:40 ` Davidlohr Bueso
2013-06-12 21:06 ` Raymond Jennings
2013-06-12 23:32 ` Al Viro
2013-06-13 0:01 ` Linus Torvalds
2013-06-13 0:20 ` Al Viro
2013-06-13 0:38 ` Linus Torvalds
2013-06-13 0:49 ` Al Viro
2013-06-13 0:59 ` Linus Torvalds
2013-06-14 15:00 ` Waiman Long
2013-06-14 15:37 ` Linus Torvalds
2013-06-14 18:17 ` Waiman Long
2013-06-15 1:26 ` Benjamin Herrenschmidt
2013-06-15 3:36 ` Waiman Long
2013-06-12 20:37 ` Linus Torvalds
2013-06-12 18:18 ` Steven Rostedt
2013-06-11 9:56 ` Paul E. McKenney
2013-06-11 15:00 ` Paul E. McKenney
2013-06-11 1:04 ` Steven Rostedt
2013-06-11 9:52 ` Paul E. McKenney
2013-06-11 14:48 ` Lai Jiangshan
2013-06-11 15:10 ` Lai Jiangshan
2013-06-11 16:48 ` Paul E. McKenney
2013-06-11 17:17 ` Linus Torvalds
2013-06-11 17:30 ` Paul E. McKenney
2013-06-11 16:21 ` Paul E. McKenney
2013-06-11 15:57 ` Waiman Long
2013-06-11 16:20 ` Steven Rostedt
2013-06-11 16:43 ` Paul E. McKenney
2013-06-11 17:13 ` Steven Rostedt
2013-06-11 17:43 ` Paul E. McKenney
2013-06-11 17:35 ` Waiman Long
2013-06-11 16:36 ` Paul E. McKenney [this message]
2013-06-11 17:01 ` Steven Rostedt
2013-06-11 17:16 ` Paul E. McKenney
2013-06-11 18:41 ` Waiman Long
2013-06-11 18:54 ` Davidlohr Bueso
2013-06-11 19:49 ` Paul E. McKenney
2013-06-11 20:09 ` Steven Rostedt
2013-06-11 20:32 ` Paul E. McKenney
2013-06-11 20:53 ` Steven Rostedt
2013-06-11 20:25 ` Jason Low
2013-06-11 20:36 ` Paul E. McKenney
2013-06-11 20:56 ` Steven Rostedt
2013-06-11 21:09 ` Paul E. McKenney
2013-06-12 1:19 ` Lai Jiangshan
2013-06-12 1:58 ` Steven Rostedt
2013-06-12 10:12 ` Paul E. McKenney
2013-06-12 11:06 ` Lai Jiangshan
2013-06-12 14:21 ` Paul E. McKenney
2013-06-12 14:15 ` Lai Jiangshan
2013-06-12 14:44 ` Paul E. McKenney
2013-06-11 17:02 ` [PATCH RFC ticketlock] v2 " Paul E. McKenney
2013-06-11 17:35 ` Linus Torvalds
2013-06-11 17:49 ` Paul E. McKenney
2013-06-11 17:36 ` Steven Rostedt
2013-06-11 17:52 ` Paul E. McKenney
2013-06-12 15:40 ` [PATCH RFC ticketlock] v3 " Paul E. McKenney
2013-06-12 16:13 ` Lai Jiangshan
2013-06-12 16:59 ` Paul E. McKenney
2013-06-13 2:55 ` Lai Jiangshan
2013-06-13 15:22 ` Paul E. McKenney
2013-06-13 23:25 ` Lai Jiangshan
2013-06-13 23:57 ` Paul E. McKenney
2013-06-14 1:28 ` Lai Jiangshan
2013-06-14 23:49 ` Paul E. McKenney
2013-06-14 7:12 ` Lai Jiangshan
2013-06-14 23:46 ` Paul E. McKenney
[not found] ` <CAC4Lta3dpTDc19rXLVQkZrxbu8AJL+Foc6ocAktUAozCpk2-Mg@mail.gmail.com>
2013-07-01 9:19 ` Raghavendra KT
2013-07-02 5:56 ` Paul E. McKenney
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=20130611163607.GG5146@linux.vnet.ibm.com \
--to=paulmck@linux.vnet.ibm.com \
--cc=Valdis.Kletnieks@vt.edu \
--cc=akpm@linux-foundation.org \
--cc=darren@dvhart.com \
--cc=dhowells@redhat.com \
--cc=dipankar@in.ibm.com \
--cc=edumazet@google.com \
--cc=fweisbec@gmail.com \
--cc=josh@joshtriplett.org \
--cc=laijs@cn.fujitsu.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mathieu.desnoyers@efficios.com \
--cc=mingo@elte.hu \
--cc=niv@us.ibm.com \
--cc=peterz@infradead.org \
--cc=rostedt@goodmis.org \
--cc=sbw@mit.edu \
--cc=tglx@linutronix.de \
--cc=torvalds@linux-foundation.org \
--cc=waiman.long@hp.com \
/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
Powered by JetHome