Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1651518 > unrolled thread
| Started by | Pasha Tatashin <pasha.tatashin@oracle.com> |
|---|---|
| First post | 2017-05-26 18:50 +0200 |
| Last post | 2017-06-01 10:50 +0200 |
| Articles | 7 — 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.
Re: [v3 0/9] parallelized "struct page" zeroing Pasha Tatashin <pasha.tatashin@oracle.com> - 2017-05-26 18:50 +0200
Re: [v3 0/9] parallelized "struct page" zeroing Michal Hocko <mhocko@kernel.org> - 2017-05-29 14:00 +0200
Re: [v3 0/9] parallelized "struct page" zeroing Pasha Tatashin <pasha.tatashin@oracle.com> - 2017-05-30 19:20 +0200
Re: [v3 0/9] parallelized "struct page" zeroing Michal Hocko <mhocko@kernel.org> - 2017-05-31 18:40 +0200
Re: [v3 0/9] parallelized "struct page" zeroing David Miller <davem@davemloft.net> - 2017-05-31 19:00 +0200
Re: [v3 0/9] parallelized "struct page" zeroing Pasha Tatashin <pasha.tatashin@oracle.com> - 2017-06-01 05:40 +0200
Re: [v3 0/9] parallelized "struct page" zeroing Michal Hocko <mhocko@kernel.org> - 2017-06-01 10:50 +0200
| From | Pasha Tatashin <pasha.tatashin@oracle.com> |
|---|---|
| Date | 2017-05-26 18:50 +0200 |
| Subject | Re: [v3 0/9] parallelized "struct page" zeroing |
| Message-ID | <tLqB3-8i8-11@gated-at.bofh.it> |
Hi Michal, I have considered your proposals: 1. Making memset(0) unconditional inside __init_single_page() is not going to work because it slows down SPARC, and ppc64. On SPARC even the BSTI optimization that I have proposed earlier won't work, because after consulting with other engineers I was told that stores (without loads!) after BSTI without membar are unsafe 2. Adding ARCH_WANT_LARGE_PAGEBLOCK_INIT is not going to solve the problem, because while arch might want a large memset(), it still wants to get the benefit of parallelized struct page initialization. 3. Another approach that have I considered is moving memset() above __init_single_page() and do it in a larger chunks. However, this solution is also not going to work, because inside the loops, there are cases where "struct page"s are skipped, so every single page is checked: early_pfn_valid(pfn), early_pfn_in_nid(), and also mirroed_kernelcore cases. > I wouldn't be so sure about this. If any other platform has a similar > issues with small memset as sparc then the overhead is just papered over > by parallel initialization. That is true, and that is fine, because parallelization gives an order of magnitude better improvements compared to trade of slower single thread performance. Remember, this will happen during boot and memory hotplug only, and not something that will eat up computing resources during runtime. So, at the moment I cannot really find a better solution compared to what I have proposed: do memset() inside __init_single_page() only when deferred initialization is enabled. Pasha
[toc] | [next] | [standalone]
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2017-05-29 14:00 +0200 |
| Message-ID | <tMrv4-7MV-25@gated-at.bofh.it> |
| In reply to | #1651518 |
On Fri 26-05-17 12:45:55, Pasha Tatashin wrote: > Hi Michal, > > I have considered your proposals: > > 1. Making memset(0) unconditional inside __init_single_page() is not going > to work because it slows down SPARC, and ppc64. On SPARC even the BSTI > optimization that I have proposed earlier won't work, because after > consulting with other engineers I was told that stores (without loads!) > after BSTI without membar are unsafe Could you be more specific? E.g. how are other stores done in __init_single_page safe then? I am sorry to be dense here but how does the full 64B store differ from other stores done in the same function. [...] > So, at the moment I cannot really find a better solution compared to what I > have proposed: do memset() inside __init_single_page() only when deferred > initialization is enabled. As I've already said I am not going to block your approach I was just hoping for something that doesn't depend on the deferred initialization. Especially when the struct page is a small objects and it makes sense to initialize it completely at a single page. Writing to a single cache line should simply not add memory traffic for exclusive cache line and struct pages are very likely to exclusive at that stage. If that doesn't fly then be it but I have to confess I still do not understand why that is not the case. -- Michal Hocko SUSE Labs
[toc] | [prev] | [next] | [standalone]
| From | Pasha Tatashin <pasha.tatashin@oracle.com> |
|---|---|
| Date | 2017-05-30 19:20 +0200 |
| Message-ID | <tMSYi-1K4-1@gated-at.bofh.it> |
| In reply to | #1652460 |
> Could you be more specific? E.g. how are other stores done in > __init_single_page safe then? I am sorry to be dense here but how does > the full 64B store differ from other stores done in the same function. Hi Michal, It is safe to do regular 8-byte and smaller stores (stx, st, sth, stb) without membar, but they are slower compared to STBI which require a membar before memory can be accessed. So when on SPARC we zero a larger span of memory it is faster to use STBI, and do one membar at the end. This is why for single thread it is faster to zero multiple pages of memory and than initialize only fields that are needed in "struct page". I believe the same is true for ppc64, as they clear the whole cacheline 128-bytes at a time with larger memsets. Pasha
[toc] | [prev] | [next] | [standalone]
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2017-05-31 18:40 +0200 |
| Message-ID | <tNeP8-7dL-13@gated-at.bofh.it> |
| In reply to | #1653413 |
On Tue 30-05-17 13:16:50, Pasha Tatashin wrote: > >Could you be more specific? E.g. how are other stores done in > >__init_single_page safe then? I am sorry to be dense here but how does > >the full 64B store differ from other stores done in the same function. > > Hi Michal, > > It is safe to do regular 8-byte and smaller stores (stx, st, sth, stb) > without membar, but they are slower compared to STBI which require a membar > before memory can be accessed. OK, so why cannot we make zero_struct_page 8x 8B stores, other arches would do memset. You said it would be slower but would that be measurable? I am sorry to be so persistent here but I would be really happier if this didn't depend on the deferred initialization. If this is absolutely a no-go then I can live with that of course. -- Michal Hocko SUSE Labs
[toc] | [prev] | [next] | [standalone]
| From | David Miller <davem@davemloft.net> |
|---|---|
| Date | 2017-05-31 19:00 +0200 |
| Message-ID | <tNf8u-7mc-1@gated-at.bofh.it> |
| In reply to | #1654441 |
From: Michal Hocko <mhocko@kernel.org> Date: Wed, 31 May 2017 18:31:31 +0200 > On Tue 30-05-17 13:16:50, Pasha Tatashin wrote: >> >Could you be more specific? E.g. how are other stores done in >> >__init_single_page safe then? I am sorry to be dense here but how does >> >the full 64B store differ from other stores done in the same function. >> >> Hi Michal, >> >> It is safe to do regular 8-byte and smaller stores (stx, st, sth, stb) >> without membar, but they are slower compared to STBI which require a membar >> before memory can be accessed. > > OK, so why cannot we make zero_struct_page 8x 8B stores, other arches > would do memset. You said it would be slower but would that be > measurable? I am sorry to be so persistent here but I would be really > happier if this didn't depend on the deferred initialization. If this is > absolutely a no-go then I can live with that of course. It is measurable. That's the impetus for this work in the first place. When the do the memory barrier, the whole store buffer flushes because the memory barrier is done with a dependency on the next load or store operation, one of which the caller is going to do immediately.
[toc] | [prev] | [next] | [standalone]
| From | Pasha Tatashin <pasha.tatashin@oracle.com> |
|---|---|
| Date | 2017-06-01 05:40 +0200 |
| Message-ID | <tNp7P-5BO-3@gated-at.bofh.it> |
| In reply to | #1654441 |
> OK, so why cannot we make zero_struct_page 8x 8B stores, other arches
> would do memset. You said it would be slower but would that be
> measurable? I am sorry to be so persistent here but I would be really
> happier if this didn't depend on the deferred initialization. If this is
> absolutely a no-go then I can live with that of course.
Hi Michal,
This is actually a very good idea. I just did some measurements, and it
looks like performance is very good.
Here is data from SPARC-M7 with 3312G memory with single thread performance:
Current:
memset() in memblock allocator takes: 8.83s
__init_single_page() take: 8.63s
Option 1:
memset() in __init_single_page() takes: 61.09s (as we discussed because
of membar overhead, memset should really be optimized to do STBI only
when size is 1 page or bigger).
Option 2:
8 stores (stx) in __init_single_page(): 8.525s!
So, even for single thread performance we can double the initialization
speed of "struct page" on SPARC by removing memset() from memblock, and
using 8 stx in __init_single_page(). It appears we never miss L1 in
__init_single_page() after the initial 8 stx.
I will update patches with memset() on other platforms, and stx on SPARC.
My experimental code looks like this:
static void __meminit __init_single_page(struct page *page, unsigned
long pfn, unsigned long zone, int nid)
{
__asm__ __volatile__(
"stx %%g0, [%0 + 0x00]\n"
"stx %%g0, [%0 + 0x08]\n"
"stx %%g0, [%0 + 0x10]\n"
"stx %%g0, [%0 + 0x18]\n"
"stx %%g0, [%0 + 0x20]\n"
"stx %%g0, [%0 + 0x28]\n"
"stx %%g0, [%0 + 0x30]\n"
"stx %%g0, [%0 + 0x38]\n"
:
:"r"(page));
set_page_links(page, zone, nid, pfn);
init_page_count(page);
page_mapcount_reset(page);
page_cpupid_reset_last(page);
INIT_LIST_HEAD(&page->lru);
#ifdef WANT_PAGE_VIRTUAL
/* The shift won't overflow because ZONE_NORMAL is below 4G. */
if (!is_highmem_idx(zone))
set_page_address(page, __va(pfn << PAGE_SHIFT));
#endif
}
Thank you,
Pasha
[toc] | [prev] | [next] | [standalone]
| From | Michal Hocko <mhocko@kernel.org> |
|---|---|
| Date | 2017-06-01 10:50 +0200 |
| Message-ID | <tNtXQ-fI-13@gated-at.bofh.it> |
| In reply to | #1654785 |
On Wed 31-05-17 23:35:48, Pasha Tatashin wrote: > >OK, so why cannot we make zero_struct_page 8x 8B stores, other arches > >would do memset. You said it would be slower but would that be > >measurable? I am sorry to be so persistent here but I would be really > >happier if this didn't depend on the deferred initialization. If this is > >absolutely a no-go then I can live with that of course. > > Hi Michal, > > This is actually a very good idea. I just did some measurements, and it > looks like performance is very good. > > Here is data from SPARC-M7 with 3312G memory with single thread performance: > > Current: > memset() in memblock allocator takes: 8.83s > __init_single_page() take: 8.63s > > Option 1: > memset() in __init_single_page() takes: 61.09s (as we discussed because of > membar overhead, memset should really be optimized to do STBI only when size > is 1 page or bigger). > > Option 2: > > 8 stores (stx) in __init_single_page(): 8.525s! > > So, even for single thread performance we can double the initialization > speed of "struct page" on SPARC by removing memset() from memblock, and > using 8 stx in __init_single_page(). It appears we never miss L1 in > __init_single_page() after the initial 8 stx. OK, that is good to hear and it actually matches my understanding that writes to a single cacheline should add an overhead. Thanks! -- Michal Hocko SUSE Labs
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web