From: Neil Horman <nhorman@tuxdriver.com>
To: "Richardson, Bruce" <bruce.richardson@intel.com>
Cc: "dev@dpdk.org" <dev@dpdk.org>
Subject: Re: [dpdk-dev] [PATCH v2 2/5] distributor: new packet distributor library
Date: Tue, 3 Jun 2014 07:01:25 -0400 [thread overview]
Message-ID: <20140603110125.GA20038@hmsreliant.think-freely.org> (raw)
In-Reply-To: <59AF69C657FD0841A61C55336867B5B01AA31639@IRSMSX103.ger.corp.intel.com>
On Mon, Jun 02, 2014 at 09:40:04PM +0000, Richardson, Bruce wrote:
>
>
> > -----Original Message-----
> > From: Neil Horman [mailto:nhorman@tuxdriver.com]
> > Sent: Thursday, May 29, 2014 6:48 AM
> > To: Richardson, Bruce
> > Cc: dev@dpdk.org
> > Subject: Re: [dpdk-dev] [PATCH v2 2/5] distributor: new packet distributor library
> >
> > > +
> > > +/* flush the distributor, so that there are no outstanding packets in flight or
> > > + * queued up. */
> > Its not clear to me that this is a distributor only function. You modified the
> > comments to indicate that lcores can't preform double duty as both a worker
> > and
> > a distributor, which is fine, but it implies that there is a clear distinction
> > between functions that are 'worker' functions and 'distributor' functions.
> > While its for the most part clear-ish (workers call rte_distributor_get_pkt and
> > rte_distibutor_return_pkt, distibutors calls rte_distributor_create/process.
> > This is in a grey area. the analogy I'm thinking of here are kernel workqueues.
> > Theres a specific workqueue thread that processes the workqueue, but any
> > process
> > can sync or flush the workqueue, leading me to think this process can be called
> > by a worker lcore.
>
> I can update comments here further, but I was hoping the way things were right now was clear enough. In the header and C files, I have the functions explicitly split up into distributor and worker function sets, with a big block of text in the header at the start of each section explaining the threading use of the follow functions.
>
Very well, we can let use be the determinant here. We can leave it as is, and
if reports of lockups come in, we can change it, otherwise no harm done.
> >
> > > +int
> > > +rte_distributor_flush(struct rte_distributor *d)
> > > +{
> > > + unsigned wkr, total_outstanding = 0;
> > > + unsigned flushed = 0;
> > > + unsigned ret_start = d->returns.start,
> > > + ret_count = d->returns.count;
> > > +
> > > + for (wkr = 0; wkr < d->num_workers; wkr++)
> > > + total_outstanding += d->backlog[wkr].count +
> > > + !!(d->in_flight_tags[wkr]);
> > > +
> > > + wkr = 0;
> > > + while (flushed < total_outstanding) {
> > > +
> > > + if (d->in_flight_tags[wkr] != 0 || d->backlog[wkr].count) {
> > > + const int64_t data = d->bufs[wkr].bufptr64;
> > > + uintptr_t oldbuf = 0;
> > > +
> > > + if (data & RTE_DISTRIB_GET_BUF) {
> > > + flushed += (d->in_flight_tags[wkr] != 0);
> > > + if (d->backlog[wkr].count) {
> > > + d->bufs[wkr].bufptr64 =
> > > + backlog_pop(&d-
> > >backlog[wkr]);
> > > + /* we need to mark something as being
> > > + * in-flight, but it doesn't matter what
> > > + * as we never check it except
> > > + * to check for non-zero.
> > > + */
> > > + d->in_flight_tags[wkr] = 1;
> > > + } else {
> > > + d->bufs[wkr].bufptr64 =
> > > +
> > RTE_DISTRIB_GET_BUF;
> > > + d->in_flight_tags[wkr] = 0;
> > > + }
> > > + oldbuf = data >> RTE_DISTRIB_FLAG_BITS;
> > > + } else if (data & RTE_DISTRIB_RETURN_BUF) {
> > > + if (d->backlog[wkr].count == 0 ||
> > > + move_backlog(d, wkr) == 0) {
> > > + /* only if we move backlog,
> > > + * process this packet */
> > > + d->bufs[wkr].bufptr64 = 0;
> > > + oldbuf = data >>
> > RTE_DISTRIB_FLAG_BITS;
> > > + flushed++;
> > > + d->in_flight_tags[wkr] = 0;
> > > + }
> > > + }
> > > +
> > > + store_return(oldbuf, d, &ret_start, &ret_count);
> > > + }
> > > +
> > I know the comments for move_backlog say you use that function here rather
> > than
> > what you do in distributor_process because you're tracking the flush count here.
> > That said, if you instead recomputed the total_outstanding count on each loop
> > iteration, and tested it for 0, I think you could just reduce the flush
> > operation to a looping call to rte_distributor_process. It would save you
> > having to maintain the flush code and the move_backlog code separately, which
> > would be a nice savings.
>
> Yes, agreed, I should have spotted that myself. I'll look to rework this as soon as I can.
>
Ok, thanks.
> >
> > > + if (++wkr == d->num_workers)
> > > + wkr = 0;
> > Nit: wkr = ++wkr % d->num_workers avoids the additional branch in your loop
> >
> a) branch should be easily predictable as the number of workers doesn't change. So long as branch doesn't mis-predict there should be little or no perf penalty to having it.
> b) The compare plus update can also be done branchless using a "cmov" instruction if we want branch free code.
> c) The modulus operator is very slow and takes far more cycles than a branch would do. If we could limit the number of workers to a power of two, then an & operation would work nicely, but that is too big a restriction to have.
> So, in short, I think I'll keep this snippet as-is. :-)
>
Yup, you're right, confirmed it with perf. Thanks!
neil
next prev parent reply other threads:[~2014-06-03 11:01 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-05-20 10:00 [dpdk-dev] [PATCH 0/4] New library: rte_distributor Bruce Richardson
2014-05-20 10:00 ` [dpdk-dev] [PATCH 1/4] eal: add tailq for new distributor component Bruce Richardson
2014-05-20 10:00 ` [dpdk-dev] [PATCH 2/4] distributor: new packet distributor library Bruce Richardson
2014-05-20 18:18 ` Neil Horman
2014-05-21 10:21 ` Richardson, Bruce
2014-05-21 15:23 ` Neil Horman
2014-05-20 10:00 ` [dpdk-dev] [PATCH 3/4] distributor: add distributor library to build Bruce Richardson
2014-05-20 10:00 ` [dpdk-dev] [PATCH 4/4] distributor: add unit tests for distributor lib Bruce Richardson
2014-05-20 10:38 ` [dpdk-dev] [PATCH 0/4] New library: rte_distributor Neil Horman
2014-05-20 11:02 ` Richardson, Bruce
2014-05-20 17:14 ` Neil Horman
2014-05-20 19:32 ` Richardson, Bruce
2014-05-27 22:32 ` Thomas Monjalon
2014-05-28 8:48 ` Richardson, Bruce
2014-05-29 10:12 ` [dpdk-dev] [PATCH v2 0/5] " Bruce Richardson
2014-06-05 1:58 ` Cao, Waterman
2014-06-12 13:57 ` Thomas Monjalon
2014-05-29 10:12 ` [dpdk-dev] [PATCH v2 1/5] eal: add tailq for new distributor component Bruce Richardson
2014-05-29 10:12 ` [dpdk-dev] [PATCH v2 2/5] distributor: new packet distributor library Bruce Richardson
2014-05-29 13:48 ` Neil Horman
2014-06-02 21:40 ` Richardson, Bruce
2014-06-03 11:01 ` Neil Horman [this message]
2014-06-03 14:33 ` Richardson, Bruce
2014-06-03 14:51 ` Neil Horman
2014-06-03 18:04 ` [dpdk-dev] [PATCH v3 " Bruce Richardson
2014-06-03 18:38 ` Neil Horman
2014-05-29 10:12 ` [dpdk-dev] [PATCH v2 3/5] distributor: add distributor library to build Bruce Richardson
2014-05-29 10:12 ` [dpdk-dev] [PATCH v2 4/5] distributor: add unit tests for distributor lib Bruce Richardson
2014-05-29 10:12 ` [dpdk-dev] [PATCH v2 5/5] docs: add distributor lib to API docs Bruce Richardson
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=20140603110125.GA20038@hmsreliant.think-freely.org \
--to=nhorman@tuxdriver.com \
--cc=bruce.richardson@intel.com \
--cc=dev@dpdk.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;
as well as URLs for NNTP newsgroup(s).