vector aligné

vector aligné - C++ - Programmation

Marsh Posté le 23-11-2010 à 10:48:12    

Tout est dans le titre, comment je peux faire un vector aligné sur 16 octets?

Reply

Marsh Posté le 23-11-2010 à 10:48:12   

Reply

Marsh Posté le 24-11-2010 à 09:33:07    

on passe par un allcoator custom. Mais premiere etape: savori aligner de la memoire ;0
Allons y :
 
Allocation bas niveau alignée
Sous pas mal de systeme, y a une fonction tte faites. Sinon, on va faire du pointeur stashing
 

Code :
  1. #if ( (defined _GNU_SOURCE) \
  2.       || ((defined _XOPEN_SOURCE) && (_XOPEN_SOURCE >= 600)) \
  3.       ) \
  4.      && (defined _POSIX_ADVISORY_INFO) && (_POSIX_ADVISORY_INFO > 0)
  5. #include <cstdlib>
  6. #include <cstring>
  7. #define SUPPORT_POSIX_MEMALIGN
  8. #endif
  9. void* allocate( std::size_t nbytes )
  10. {
  11.     void *result;
  12.     BOOST_STATIC_CONSTANT(std::size_t, align = 16 );
  13. #if defined(SUPPORT_POSIX_MEMALIGN)
  14.     //////////////////////////////////////////////////////////////////////////////
  15.     // POSIX systems use posix_memalign
  16.     //////////////////////////////////////////////////////////////////////////////
  17.     if(posix_memalign(&result, align, nbytes))
  18.     {
  19.       throw std::bad_alloc();
  20.       result = 0;
  21.     }
  22. #elif defined (_MSC_VER)
  23.     //////////////////////////////////////////////////////////////////////////////
  24.     // MSVC systems use _aligned_malloc
  25.     //////////////////////////////////////////////////////////////////////////////
  26.     if( !(result = _aligned_malloc(nbytes, align) ) )
  27.     {
  28.       throw std::bad_alloc();
  29.       result = 0;
  30.     }
  31. #else
  32.     //////////////////////////////////////////////////////////////////////////////
  33.     // Other systems do the funky pointer stashing
  34.     //////////////////////////////////////////////////////////////////////////////
  35.     void *base;
  36.     BOOST_STATIC_CONSTANT(std::size_t, fix = ~(std::size_t(align-1)));
  37.     if( !(base = ::malloc(nbytes+align+sizeof(void*))) )
  38.     {
  39.       throw std::bad_alloc();
  40.       result = 0;
  41.     }
  42.     else
  43.     {
  44.       std::size_t ref = reinterpret_cast<std::size_t>(base)+sizeof(void*);
  45.       std::size_t stashed = (ref & fix) + align;
  46.       result = reinterpret_cast<void*>(stashed);
  47.       reinterpret_cast<void**>(result)[-1] = base;
  48.     }
  49. #endif
  50.     return result;
  51. }
  52. void deallocate( void* ptr, std::size_t )
  53.   {
  54. #if defined(SUPPORT_POSIX_MEMALIGN)
  55.     //////////////////////////////////////////////////////////////////////////////
  56.     // POSIX systems use free
  57.     //////////////////////////////////////////////////////////////////////////////
  58.     if(ptr) ::free(ptr);
  59. #elif (defined _MSC_VER)
  60.     //////////////////////////////////////////////////////////////////////////////
  61.     // MSVC systems use _aligned_free
  62.     //////////////////////////////////////////////////////////////////////////////
  63.     if(ptr)_aligned_free(ptr);
  64. #else
  65.     //////////////////////////////////////////////////////////////////////////////
  66.     // Other systems do the funky pointer stashing
  67.     //////////////////////////////////////////////////////////////////////////////
  68.     if(ptr) ::free( reinterpret_cast<void**>(ptr)[- 1] );
  69. #endif
  70.   }


 
Allocator custom

Code :
  1. template<class T> struct aligned_allocator
  2.   {
  3.     ////////////////////////////////////////////////////////////////////////////
  4.     // Internal typedefs
  5.     ////////////////////////////////////////////////////////////////////////////
  6.     typedef T value_type;
  7.     typedef T* pointer;
  8.     typedef T const* const_pointer;
  9.     typedef T& reference;
  10.     typedef T const& const_reference;
  11.     typedef std::size_t size_type;
  12.     typedef std::ptrdiff_t difference_type;
  13.     template<class U> struct rebind { typedef aligned_allocator<U> other; };
  14.     ////////////////////////////////////////////////////////////////////////////
  15.     // Ctor/dtor
  16.     ////////////////////////////////////////////////////////////////////////////
  17.                       aligned_allocator() {}
  18.     template<class U> allocator(aligned_allocator<U> const& ) {}
  19.                      ~aligned_allocator() {}
  20.     aligned_allocator& operator=(aligned_allocator const& ) { return *this; }
  21.     ////////////////////////////////////////////////////////////////////////////
  22.     // Address handling
  23.     ////////////////////////////////////////////////////////////////////////////
  24.     pointer address(reference r) { return &r; }
  25.     const_pointer address(const_reference r) { return &r; }
  26.     ////////////////////////////////////////////////////////////////////////////
  27.     // Size handling
  28.     ////////////////////////////////////////////////////////////////////////////
  29.     size_type max_size() const { return size_type(~0); }
  30.     ////////////////////////////////////////////////////////////////////////////
  31.     // Object lifetime handling
  32.     ////////////////////////////////////////////////////////////////////////////
  33.     void construct(pointer p, const T& t)
  34.     {
  35.       p = new (p) value_type(t);
  36.     }
  37.     void destroy(pointer p) { p->~value_type(); }
  38.     ////////////////////////////////////////////////////////////////////////////
  39.     // Memory handling
  40.     ////////////////////////////////////////////////////////////////////////////
  41.     pointer allocate( size_type c, const void* = 0 ) const
  42.     {
  43.       void* ptr = allocate(c*sizeof(value_type));
  44.       return reinterpret_cast<pointer>(ptr);
  45.     }
  46.     void deallocate (pointer p, size_type s) const
  47.     {
  48.       deallocate(p,s*sizeof(value_type));
  49.     }
  50.   };


 
Utilisation

Code :
  1. std::vector<float, aligned_allocator<float> > v(10);


 
Et voila :)
 
Note, l'alignement n'a de sens que sur des puissance de 2.
L'exercice est laissée au lecteur de rendre le aligned_allcoator template sur la valeur de l'alignement.
Sinon, tout est la : https://github.com/metascale/nt2 dans le module nt2::memory

Reply

Marsh Posté le 01-12-2010 à 20:58:21    

   pointer allocate( size_type c, const void* = 0 ) const
    {
      void* ptr = allocate(c*sizeof(value_type));
      return reinterpret_cast<pointer>(ptr);
    }
 
c pas récursif ça ?


---------------
.
Reply

Marsh Posté le 01-12-2010 à 21:10:39    

et sinon dans quel cas peut avoir besoin d'être aligné sur 16 bytes?


Message édité par Glock 17Pro le 01-12-2010 à 21:15:16

---------------
.
Reply

Marsh Posté le 01-12-2010 à 21:44:18    

avoir de la mémoire compatible avec des extensions SIMD comme Altivec et SSE.
 
Sinon, il faut bien entendu mettre un nt2::allcoate dans ton bout de code effectivement.

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed