I was looking at this example from pycapnp that appears to bypass the 
alignment-related copy whenever possible:

```

@cython.internal

cdef class _FlatArrayMessageReader(_MessageReader):

    cdef object _object_to_pin

    def __init__(self, buf, traversal_limit_in_words = None, nesting_limit 
= None):

        cdef schema_cpp.ReaderOptions opts

        cdef _AlignedBuffer aligned


        if traversal_limit_in_words is not None:

            opts.traversalLimitInWords = traversal_limit_in_words

        if nesting_limit is not None:

            opts.nestingLimit = nesting_limit


        sz = len(buf)

        if sz % 8 != 0:

            raise ValueError("input length must be a multiple of eight 
bytes")


        cdef char * ptr = buf

        if (<uintptr_t>ptr) % 8 != 0:

            aligned = _AlignedBuffer(buf)

            ptr = aligned.buf

            self._object_to_pin = aligned

        else:

            self._object_to_pin = buf


        self.thisptr = new 
schema_cpp.FlatArrayMessageReader(schema_cpp.WordArrayPtr(<schema_cpp.word*>ptr,
 
sz//8))

```


and tried a similar optimization in my application. The buffer in my 
application comes from the "builder.to_bytes()" call in pycapnp. What I 
found in my own experiment is that the buffer is never aligned and 
therefore always needs to be copied to an aligned heap-based buffer. I 
would like to be able to take advantage of this type of optimization in my 
own extension, but I don't see how, since pycapnp's "to_bytes" seems to 
always return a misaligned data buffer (at least on OS X). This is what my 
python extension code looks like. In this snippet, the argument pyBytes is 
the value returned by pycapnp's "to_bytes()" and the debug output is always 
"ZZZ NEEDS ALIGNMENT":


```

    template<class MessageType>

    static void initFromPyBytes(

      nupic::Serializable<MessageType>& obj,

      const PyObject* pyBytes)

    {

    #if !CAPNP_LITE

      const char* srcBytes = nullptr;

      Py_ssize_t srcNumBytes = 0;


      // NOTE: srcBytes will be set to point to the internal buffer inside

      // pyRegionProtoBytes'

      PyString_AsStringAndSize(const_cast<PyObject*>(pyBytes),

                               const_cast<char**>(&srcBytes),

                               &srcNumBytes);


      if (srcNumBytes % sizeof(capnp::word) != 0)

      {

        throw std::logic_error(

          "PyCapnpHelper.initFromPyBytes input length must be a multiple of 
"

          "capnp::word.");

      }

      const int srcNumWords = srcNumBytes / sizeof(capnp::word);


      // Ensure alignment on capnp::word boundary; copy only if we have to

      kj::Array<capnp::word> aligned;

      if ((reinterpret_cast<uintptr_t>(srcBytes) % sizeof(capnp::word)) != 
0)

      {

        NTA_DEBUG << "ZZZ NEEDS ALIGNMENT";

        aligned = kj::heapArray<capnp::word>(srcNumWords);

        memcpy(aligned.asBytes().begin(), srcBytes, srcNumBytes); // copy

        srcBytes = reinterpret_cast<char*>(aligned.asBytes().begin());

      }

      else

      {

        NTA_DEBUG << "ZZZ ALREADY ALIGNED";

      }


      kj::ArrayPtr<capnp::word> wordArrayPtr(

        reinterpret_cast<capnp::word*>(const_cast<char*>(srcBytes)),

        srcNumWords);

      capnp::FlatArrayMessageReader reader(wordArrayPtr); // copy ?

      typename MessageType::Reader proto = reader.getRoot<MessageType>();

      obj.read(proto);

```

-- 
You received this message because you are subscribed to the Google Groups 
"Cap'n Proto" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
Visit this group at https://groups.google.com/group/capnproto.

Reply via email to