Boost logo

Boost :

Subject: Re: [boost] [Endian] Performance
From: john filo (filo_at_[hidden])
Date: 2011-09-09 15:14:06


On 09/09/2011 10:45 AM, Beman Dawes wrote:
> I'm missing something. Could you please post the full function, without any
> preprocessing statements, where the aliasing issue is arising?
I should have provided more context. Sorry about that. It was an
addition to the body of the byteswap function in Phil's test code that
sparked this whole performance discussion. With all the various
byteswap implementations stripped away, the code becomes:

     #include <cstdint>
     #include <iostream>
     #include <boost/endian/integers.hpp>

     using std::uint32_t;
     using namespace boost::endian;

     static inline uint32_t byteswap(uint32_t src)
     {
         return *reinterpret_cast<const ubig32_t*>(&src);
     }

     int main()
     {
         uint32_t s = 0;
         for (uint32_t i = 0; i < 1000000000; ++i)
             s += byteswap(x[i]);

         std::cout << s << "\n";
      }

I did this to compare timing of your endian<> class to your reorder
functions, and to show that the former was considerably more efficient
than the latter and that you could just implement reorder() in terms of
endian<> using the reinterpret_cast above.

I don't fully grasp the C++ aliaising rules, but Matt claims the above
reinterpret_cast can (or does) result in undefined behavior. In this
particular case, gcc doesn't complain about any aliasing problems and it
does produce the correct answer, but that doesn't mean my code is correct.

Oddly enough, when I used a trick I've used in the past to get rid gcc
aliasing warnings, gcc started complaining the I had aliasing problems
in some cases, so clearly I *really* don't understand the aliasing rules
in C++. The trick I used is to use a union, which I though was the
recommended way to alias a chunk of memory to multiple types. I.e.

     template<typename DST, typename SRC>
     DST aliased_ptr_cast(DST dst)
     {
         union {
             SRC src;
             DST dst;
         } u;
         u.src = src;
         return u.dst;
     }

inline uint32_t byteswap_big(uint32_t src)
     {
         return *aliased_ptr_cast<const ubig32_t*>(&src);
     }

Using the above code, along with main() defined further up, the app
compiles warning free and produces the correct answer on
linux/intel/g++-4.4. If I change the type in the "aliased_ptr_cast"
from ubig32_t to either ulittle32_t or unative32_t, I start getting
aliasing warnings. I clearly have some learning to do.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk