Implication of GCC warning: ignoring attributes on

2020-07-02 10:17发布

I'm using __m256 as an argument for a template class (see code below). When compiling with g++ version 6.2 on Ubuntu 16.10 (Yakkety Yak), it warns me about attributes being ignored on the template argument:

warning: ignoring attributes on template argument ‘__m256 {aka __vector(8) float}’ [-Wignored-attributes] typedef vec_array<__m256> vec256

The __m256 type seems to have some attributes concerning alignment (and maybe some others?). The sole purpose of this primitive container class shown below (and which generates the warning) is to handle memory alignment on the heap for these special Intel variables (__m256, __m128, etc.).

When I use this container class in my overall program, it seems to be working fine. However, my question is what the implications are when GCC is ignoring these attributes (I have already read what the GCC manual has to say on the issue).

  1. Is there a good way of getting rid of these warnings?
  2. Do I have to worry about this?
  3. What is the worst that can happen if I ignore this warning?

For reference, the code below produces this warning.

///////////////////////////////////////////////////////////////////////////////
// System includes:

#include <x86intrin.h>
#include <cstdint>

static const size_t AVX_alignment = 32;

template<typename VecT>
class vec_array
{
protected:
   VecT*  m_pdata;
   size_t m_num_vector_elements;

public:
   vec_array();
   vec_array(size_t num_vector_elements);

   virtual ~vec_array();

   void allocate(size_t num_vector_elements);
   void free();

};

template<typename VecT>
vec_array<VecT>::vec_array() : m_pdata(nullptr), m_num_vector_elements(0)
{}

template<typename VecT>
vec_array<VecT>::vec_array(size_t num_vector_elements) : m_pdata(nullptr),
m_num_vector_elements(num_vector_elements)
{
   allocate(num_vector_elements);
}

template<typename VecT>
vec_array<VecT>::~vec_array()
{
   free();
}

template<typename VecT>
void vec_array<VecT>::allocate(size_t num_vector_elements)
{
   if( m_num_vector_elements == num_vector_elements)
      return;

   m_num_vector_elements = num_vector_elements;

   free();

   m_pdata = reinterpret_cast<VecT*>(_mm_malloc(m_num_vector_elements*sizeof(VecT), AVX_alignment));
}

template<typename VecT>
void vec_array<VecT>::free()
{
   if(m_pdata != nullptr)
      _mm_free(m_pdata);
}


typedef vec_array<__m256> vec256;

int main()
{
   vec256 test_vec(10);
}

标签: c++ gcc
2条回答
爱情/是我丢掉的垃圾
2楼-- · 2020-07-02 10:47

I came across the same warning but in some OpenCL code and ended up here, without looking at the code first. You can see how some people try to avoid this warning in Making std::vector allocate aligned memory, but in my opinion it just isn't worth it.

The short answer is that you don't have to worry about this, apart from CPUs that only support 128 bit AVX instructions. If the warning were serious, then the CPU would generate an exception on unaligned access.

The reason this warning appears is because the type __m256 is probably declared with an alignment specifier of probably 16 bytes. That is to say that the CPU would expect the alignment of each of the elements of the vector to be 16 bytes. However, the template for vector doesn't honor the alignment attribute.

I think that you would have to do something stupid, like a

struct stupidStruct __attribute__(packed) {
    unsigned short padding;
    std::vector<__m256> vect;
};

to force the compiler to produce code that would cause an error.

查看更多
够拽才男人
3楼-- · 2020-07-02 10:49

It is possible to get rid of these warning by wrapping the vector types such as __m256 with a structure:

struct __m256_wrapper {
    typedef __m256 VecT;
};

and use this structure as a template parameter where it is needed. So the code you provided will be changed as following:

///////////////////////////////////////////////////////////////////////////////
// System includes:

#include <x86intrin.h>
#include <cstdint>

static const size_t AVX_alignment = 32;

struct __m256_wrapper {
    typedef __m256 VecT;
};

template<typename W>
class vec_array
{
protected:
   typename W::VecT*  m_pdata;
   size_t m_num_vector_elements;

public:
   vec_array();
   vec_array(size_t num_vector_elements);

   virtual ~vec_array();

   void allocate(size_t num_vector_elements);
   void free();

};

template<typename W>
vec_array<W>::vec_array() : m_pdata(nullptr), m_num_vector_elements(0)
{}

template<typename W>
vec_array<W>::vec_array(size_t num_vector_elements) : m_pdata(nullptr),
m_num_vector_elements(num_vector_elements)
{
   allocate(num_vector_elements);
}

template<typename W>
vec_array<W>::~vec_array()
{
   free();
}

template<typename W>
void vec_array<W>::allocate(size_t num_vector_elements)
{
   if( m_num_vector_elements == num_vector_elements)
      return;

   m_num_vector_elements = num_vector_elements;

   free();

   m_pdata = reinterpret_cast<typename W::VecT*>(_mm_malloc(m_num_vector_elements*sizeof(typename W::VecT), AVX_alignment));
}

template<typename W>
void vec_array<W>::free()
{
   if(m_pdata != nullptr)
      _mm_free(m_pdata);
}


typedef vec_array<__m256_wrapper> vec256;

int main()
{
   vec256 test_vec(10);
}
查看更多
登录 后发表回答