Determining maximum possible alignment in C++

前端 未结 6 671
情歌与酒
情歌与酒 2021-01-31 18:58

Is there any portable way to determine what the maximum possible alignment for any type is?

For example on x86, SSE instructions require 16-byte alignm

6条回答
  •  时光说笑
    2021-01-31 19:22

    Unfortunately ensuring max alignment is a lot tougher than it should be, and there are no guaranteed solutions AFAIK. From the GotW blog (Fast Pimpl article):

    union max_align {
      short       dummy0;
      long        dummy1;
      double      dummy2;
      long double dummy3;
      void*       dummy4;
      /*...and pointers to functions, pointers to
           member functions, pointers to member data,
           pointers to classes, eye of newt, ...*/
    };
    
    union {
      max_align m;
      char x_[sizeofx];
    };
    

    This isn't guaranteed to be fully portable, but in practice it's close enough because there are few or no systems on which this won't work as expected.

    That's about the closest 'hack' I know for this.

    There is another approach that I've used personally for super fast allocation. Note that it is evil, but I work in raytracing fields where speed is one of the greatest measures of quality and we profile code on a daily basis. It involves using a heap allocator with pre-allocated memory that works like the local stack (just increments a pointer on allocation and decrements one on deallocation).

    I use it for Pimpls particularly. However, just having the allocator is not enough; for such an allocator to work, we have to assume that memory for a class, Foo, is allocated in a constructor, the same memory is likewise deallocated only in the destructor, and that Foo itself is created on the stack. To make it safe, I needed a function to see if the 'this' pointer of a class is on the local stack to determine if we can use our super fast heap-based stack allocator. For that we had to research OS-specific solutions: I used TIBs and TEBs for Win32/Win64, and my co-workers found solutions for Linux and Mac OS X.

    The result, after a week of researching OS-specific methods to detect stack range, alignment requirements, and doing a lot of testing and profiling, was an allocator that could allocate memory in 4 clock cycles according to our tick counter benchmarks as opposed to about 400 cycles for malloc/operator new (our test involved thread contention so malloc is likely to be a bit faster than this in single-threaded cases, perhaps a couple of hundred cycles). We added a per-thread heap stack and detected which thread was being used which increased the time to about 12 cycles, though the client can keep track of the thread allocator to get the 4 cycle allocations. It wiped out memory allocation based hotspots off the map.

    While you don't have to go through all that trouble, writing a fast allocator might be easier and more generally applicable (ex: allowing the amount of memory to allocate/deallocate to be determined at runtime) than something like max_align here. max_align is easy enough to use, but if you're after speed for memory allocations (and assuming you've already profiled your code and found hotspots in malloc/free/operator new/delete with major contributors being in code you have control over), writing your own allocator can really make the difference.

提交回复
热议问题