From: Loic Dachary <loic@dachary.org>
To: Janne Grunau <j@jannau.net>, ceph-devel@vger.kernel.org
Subject: Re: [PATCH v3 1/4] buffer: add an aligned buffer with less alignment than a page
Date: Mon, 29 Sep 2014 15:27:02 +0200 [thread overview]
Message-ID: <54295E26.4080705@dachary.org> (raw)
In-Reply-To: <1411994072-18850-2-git-send-email-j@jannau.net>
[-- Attachment #1: Type: text/plain, Size: 9410 bytes --]
Hi Janne,
I think the implementation of the bufferlist n_align_sized functions is missing. That showed when adding unit tests for them
https://github.com/dachary/ceph/commit/fd01824f1681edd0ec029b02318b6c40b923c156
Feel free to pick up where I left, I won't work on them any more today ;-)
Cheers
On 29/09/2014 14:34, Janne Grunau wrote:
> SIMD optimized erasure code computation needs aligned memory. Buffers
> aligned to a page boundary are not needed though. The buffers used
> for the erasure code computation are typical smaller than a page.
>
> The typical alignment requirements SIMD operations are 16 bytes for
> SSE2 and NEON and 32 bytes for AVX/AVX2.
>
> Signed-off-by: Janne Grunau <j@jannau.net>
> ---
> configure.ac | 9 +++++
> src/common/buffer.cc | 106 +++++++++++++++++++++++++++++++++++++++++++++++++++
> src/include/buffer.h | 15 ++++++++
> 3 files changed, 130 insertions(+)
>
> diff --git a/configure.ac b/configure.ac
> index cccf2d9..1bb27c4 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -793,6 +793,15 @@ AC_MSG_RESULT([no])
> ])
>
> #
> +# Check for functions to provide aligned memory
> +#
> +AC_CHECK_HEADERS([malloc.h])
> +AC_CHECK_FUNCS([posix_memalign _aligned_malloc memalign aligned_malloc],
> + [found_memalign=yes; break])
> +
> +AS_IF([test "x$found_memalign" != "xyes"], [AC_MSG_WARN([No function for aligned memory allocation found])])
> +
> +#
> # Check for pthread spinlock (depends on ACX_PTHREAD)
> #
> saved_LIBS="$LIBS"
> diff --git a/src/common/buffer.cc b/src/common/buffer.cc
> index af298ac..dfe887e 100644
> --- a/src/common/buffer.cc
> +++ b/src/common/buffer.cc
> @@ -30,6 +30,10 @@
> #include <sys/uio.h>
> #include <limits.h>
>
> +#ifdef HAVE_MALLOC_H
> +#include <malloc.h>
> +#endif
> +
> namespace ceph {
>
> #ifdef BUFFER_DEBUG
> @@ -155,9 +159,17 @@ static simple_spinlock_t buffer_debug_lock = SIMPLE_SPINLOCK_INITIALIZER;
> virtual int zero_copy_to_fd(int fd, loff_t *offset) {
> return -ENOTSUP;
> }
> + virtual bool is_aligned(unsigned align) {
> + assert((align >= sizeof(void *)) && (align & (align - 1)) == 0);
> + return ((intptr_t)data & (align - 1)) == 0;
> + }
> virtual bool is_page_aligned() {
> return ((long)data & ~CEPH_PAGE_MASK) == 0;
> }
> + bool is_n_align_sized(unsigned align) {
> + assert((align >= sizeof(void *)) && (align & (align - 1)) == 0);
> + return (len % align) == 0;
> + }
> bool is_n_page_sized() {
> return (len & ~CEPH_PAGE_MASK) == 0;
> }
> @@ -209,6 +221,43 @@ static simple_spinlock_t buffer_debug_lock = SIMPLE_SPINLOCK_INITIALIZER;
> }
> };
>
> + class buffer::raw_aligned : public buffer::raw {
> + unsigned _align;
> + public:
> + raw_aligned(unsigned l, unsigned align) : raw(l) {
> + _align = align;
> + assert((align >= sizeof(void *)) && (align & (align - 1)) == 0);
> + if (len) {
> +#if HAVE_POSIX_MEMALIGN
> + if (posix_memalign((void **) &data, align, len))
> + data = 0;
> +#elif HAVE__ALIGNED_MALLOC
> + data = _aligned_malloc(len, align);
> +#elif HAVE_MEMALIGN
> + data = memalign(align, len);
> +#elif HAVE_ALIGNED_MALLOC
> + data = aligned_malloc((len + align - 1) & (align - 1), align);
> +#else
> + data = malloc(len);
> +#endif
> + if (!data)
> + throw bad_alloc();
> + } else {
> + data = 0;
> + }
> + inc_total_alloc(len);
> + bdout << "raw_aligned " << this << " alloc " << (void *)data << " " << l << " " << buffer::get_total_alloc() << bendl;
> + }
> + ~raw_aligned() {
> + free(data);
> + dec_total_alloc(len);
> + bdout << "raw_aligned " << this << " free " << (void *)data << " " << buffer::get_total_alloc() << bendl;
> + }
> + raw* clone_empty() {
> + return new raw_aligned(len, _align);
> + }
> + };
> +
> #ifndef __CYGWIN__
> class buffer::raw_mmap_pages : public buffer::raw {
> public:
> @@ -334,6 +383,10 @@ static simple_spinlock_t buffer_debug_lock = SIMPLE_SPINLOCK_INITIALIZER;
> return true;
> }
>
> + bool is_aligned() {
> + return false;
> + }
> +
> bool is_page_aligned() {
> return false;
> }
> @@ -520,6 +573,9 @@ static simple_spinlock_t buffer_debug_lock = SIMPLE_SPINLOCK_INITIALIZER;
> buffer::raw* buffer::create_static(unsigned len, char *buf) {
> return new raw_static(buf, len);
> }
> + buffer::raw* buffer::create_aligned(unsigned len, unsigned align) {
> + return new raw_aligned(len, align);
> + }
> buffer::raw* buffer::create_page_aligned(unsigned len) {
> #ifndef __CYGWIN__
> //return new raw_mmap_pages(len);
> @@ -1013,6 +1069,17 @@ static simple_spinlock_t buffer_debug_lock = SIMPLE_SPINLOCK_INITIALIZER;
> return true;
> }
>
> + bool buffer::list::is_aligned(unsigned align) const
> + {
> + assert((align >= sizeof(void *)) && (align & (align - 1)) == 0);
> + for (std::list<ptr>::const_iterator it = _buffers.begin();
> + it != _buffers.end();
> + ++it)
> + if (!it->is_aligned(align))
> + return false;
> + return true;
> + }
> +
> bool buffer::list::is_page_aligned() const
> {
> for (std::list<ptr>::const_iterator it = _buffers.begin();
> @@ -1101,6 +1168,45 @@ static simple_spinlock_t buffer_debug_lock = SIMPLE_SPINLOCK_INITIALIZER;
> _buffers.push_back(nb);
> }
>
> +void buffer::list::rebuild_aligned(unsigned align)
> +{
> + std::list<ptr>::iterator p = _buffers.begin();
> + assert((align >= sizeof(void *)) && (align & (align - 1)) == 0);
> + while (p != _buffers.end()) {
> + // keep anything that's already align sized+aligned
> + if (p->is_aligned(align) && p->is_n_align_sized(align)) {
> + /*cout << " segment " << (void*)p->c_str()
> + << " offset " << ((unsigned long)p->c_str() & (align - 1))
> + << " length " << p->length()
> + << " " << (p->length() & (align - 1)) << " ok" << std::endl;
> + */
> + ++p;
> + continue;
> + }
> +
> + // consolidate unaligned items, until we get something that is sized+aligned
> + list unaligned;
> + unsigned offset = 0;
> + do {
> + /*cout << " segment " << (void*)p->c_str()
> + << " offset " << ((unsigned long)p->c_str() & (align - 1))
> + << " length " << p->length() << " " << (p->length() & (align - 1))
> + << " overall offset " << offset << " " << (offset & (align - 1))
> + << " not ok" << std::endl;
> + */
> + offset += p->length();
> + unaligned.push_back(*p);
> + _buffers.erase(p++);
> + } while (p != _buffers.end() &&
> + (!p->is_aligned(align) ||
> + !p->is_n_align_sized(align) ||
> + (offset % align)));
> + ptr nb(buffer::create_aligned(unaligned._len, align));
> + unaligned.rebuild(nb);
> + _buffers.insert(p, unaligned._buffers.front());
> + }
> +}
> +
> void buffer::list::rebuild_page_aligned()
> {
> std::list<ptr>::iterator p = _buffers.begin();
> diff --git a/src/include/buffer.h b/src/include/buffer.h
> index e5c1b50..2a32cf4 100644
> --- a/src/include/buffer.h
> +++ b/src/include/buffer.h
> @@ -124,6 +124,7 @@ private:
> */
> class raw;
> class raw_malloc;
> + class raw_aligned;
> class raw_static;
> class raw_mmap_pages;
> class raw_posix_aligned;
> @@ -144,6 +145,7 @@ public:
> static raw* create_malloc(unsigned len);
> static raw* claim_malloc(unsigned len, char *buf);
> static raw* create_static(unsigned len, char *buf);
> + static raw* create_aligned(unsigned len, unsigned align);
> static raw* create_page_aligned(unsigned len);
> static raw* create_zero_copy(unsigned len, int fd, int64_t *offset);
>
> @@ -177,7 +179,17 @@ public:
> bool at_buffer_head() const { return _off == 0; }
> bool at_buffer_tail() const;
>
> + bool is_aligned(unsigned align) const
> + {
> + assert((align >= sizeof(void *)) && (align & (align - 1)) == 0);
> + return ((intptr_t)c_str() & (align - 1)) == 0;
> + }
> bool is_page_aligned() const { return ((long)c_str() & ~CEPH_PAGE_MASK) == 0; }
> + bool is_n_align_sized(unsigned align) const
> + {
> + assert((align >= sizeof(void *)) && (align & (align - 1)) == 0);
> + return (length() % align) == 0;
> + }
> bool is_n_page_sized() const { return (length() & ~CEPH_PAGE_MASK) == 0; }
>
> // accessors
> @@ -344,7 +356,9 @@ public:
> bool contents_equal(buffer::list& other);
>
> bool can_zero_copy() const;
> + bool is_aligned(unsigned align) const;
> bool is_page_aligned() const;
> + bool is_n_align_sized(unsigned align) const;
> bool is_n_page_sized() const;
>
> bool is_zero() const;
> @@ -382,6 +396,7 @@ public:
> bool is_contiguous();
> void rebuild();
> void rebuild(ptr& nb);
> + void rebuild_aligned(unsigned align);
> void rebuild_page_aligned();
>
> // sort-of-like-assignment-op
>
--
Loïc Dachary, Artisan Logiciel Libre
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 263 bytes --]
next prev parent reply other threads:[~2014-09-29 13:27 UTC|newest]
Thread overview: 41+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-09-15 15:55 [PATCH 1/3] buffer: add an aligned buffer with less alignment than a page Janne Grunau
2014-09-15 15:55 ` [PATCH 2/3] ec: make use of added aligned buffers Janne Grunau
2014-09-15 17:20 ` Loic Dachary
2014-09-15 23:56 ` Ma, Jianpeng
2014-09-16 0:02 ` Sage Weil
2014-09-16 0:08 ` Ma, Jianpeng
2014-09-16 6:47 ` Loic Dachary
2014-09-16 6:59 ` Ma, Jianpeng
2014-09-16 7:55 ` Loic Dachary
2014-09-16 8:23 ` Ma, Jianpeng
2014-09-15 15:55 ` [PATCH 3/3] ceph_erasure_code_benchmark: align the encoding input Janne Grunau
2014-09-15 16:46 ` [PATCH 1/3] buffer: add an aligned buffer with less alignment than a page Loic Dachary
2014-09-18 10:33 ` v2 aligned buffer changes for erasure codes Janne Grunau
2014-09-18 10:33 ` [PATCH v2 1/3] buffer: add an aligned buffer with less alignment than a page Janne Grunau
2014-09-18 10:33 ` [PATCH v2 2/3] ec: use 32-byte aligned buffers Janne Grunau
2014-09-19 9:47 ` Loic Dachary
2014-09-18 10:33 ` [PATCH v2 3/3] ceph_erasure_code_benchmark: align the encoding input Janne Grunau
2014-09-18 12:18 ` v2 aligned buffer changes for erasure codes Andreas Joachim Peters
2014-09-18 12:34 ` Andreas Joachim Peters
2014-09-18 12:53 ` Janne Grunau
2014-09-19 9:18 ` Loic Dachary
2014-09-18 12:40 ` Janne Grunau
2014-09-18 13:01 ` Andreas Joachim Peters
2014-09-18 13:23 ` Janne Grunau
2014-09-18 14:47 ` Andreas Joachim Peters
2014-09-29 12:34 ` [PATCH v3 0/4] buffer alignment for erasure code SIMD Janne Grunau
2014-09-29 12:34 ` [PATCH v3 1/4] buffer: add an aligned buffer with less alignment than a page Janne Grunau
2014-09-29 13:12 ` Loic Dachary
2014-10-02 12:09 ` Janne Grunau
2014-09-29 13:27 ` Loic Dachary [this message]
2014-10-02 12:12 ` Janne Grunau
2014-10-02 14:17 ` Loic Dachary
2014-09-29 12:34 ` [PATCH v3 2/4] erasure code: use a function for the chunk mapping index Janne Grunau
2014-09-29 12:34 ` [PATCH v3 3/4] erasure code: use 32-byte aligned buffers Janne Grunau
2014-09-29 12:34 ` [PATCH v3 4/4] ceph_erasure_code_benchmark: use 32-byte aligned input Janne Grunau
2014-09-29 13:15 ` [PATCH v3 0/4] buffer alignment for erasure code SIMD Loic Dachary
2014-09-29 15:18 ` Milosz Tanski
2014-09-29 15:24 ` C++11 Sage Weil
2014-09-29 15:44 ` C++11 Milosz Tanski
2014-09-29 17:56 ` C++11 Wido den Hollander
2014-10-02 12:15 ` [PATCH v3 0/4] buffer alignment for erasure code SIMD Janne Grunau
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=54295E26.4080705@dachary.org \
--to=loic@dachary.org \
--cc=ceph-devel@vger.kernel.org \
--cc=j@jannau.net \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.