【问题标题】:Implication of GCC warning: ignoring attributes on template argument (-Wignored-attributes)GCC 警告的含义:忽略模板参数上的属性 (-Wignored-attributes)
【发布时间】:2017-01-16 12:19:54
【问题描述】:

我使用__m256 作为模板类的参数(参见下面的代码)。在Ubuntu 16.10 (Yakkety Yak) 上使用 g++ 6.2 版进行编译时,它会警告我模板参数上的属性被忽略:

警告:忽略模板参数“__m256 {aka __vector(8) float}”上的属性 [-Wignored-attributes] typedef vec_array<__m256> vec256

__m256 类型似乎有一些与对齐有关的属性(也许还有一些其他属性?)。下面显示的这个原始容器类(并生成警告)的唯一目的是为这些特殊的 Intel 变量(__m256__m128 等)处理堆上的内存对齐。

当我在整个程序中使用这个容器类时,它似乎工作正常。但是,我的问题是当 GCC 忽略这些属性时会产生什么影响(我已经阅读了 GCC 手册对这个问题的说明)。

  1. 有没有消除这些警告的好方法?
  2. 我需要担心这个吗?
  3. 如果我忽略此警告,可能发生的最坏情况是什么?

作为参考,下面的代码会产生这个警告。

///////////////////////////////////////////////////////////////////////////////
// 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


    【解决方案1】:

    我遇到了同样的警告,但在一些 OpenCL 代码中并最终出现在这里,而没有先查看代码。您可以在 Making std::vector allocate aligned memory 中看到有些人是如何试图避免此警告的,但在我看来,这是不值得的。

    简短的回答是,除了仅支持 128 位 AVX 指令的 CPU 之外,您不必担心这一点。如果警告很严重,那么 CPU 会在未对齐访问时产生异常。

    出现此警告的原因是__m256 类型可能是使用可能 16 字节的对齐说明符声明的。也就是说,CPU 会期望向量的每个元素的对齐为 16 字节。但是,vector 的模板不支持对齐属性。

    我认为你必须做一些愚蠢的事情,比如

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

    强制编译器生成会导致错误的代码。

    【讨论】:

    • 所以如果发生了不好的事情,那就是总线错误。
    【解决方案2】:

    可以通过使用结构包装诸如__m256 之类的向量类型来消除这些警告:

    struct __m256_wrapper {
        typedef __m256 VecT;
    };
    

    并在需要时将此结构用作模板参数。因此,您提供的代码将更改如下:

    ///////////////////////////////////////////////////////////////////////////////
    // 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);
    }
    

    【讨论】:

    • if(m_pdata != nullptr) _mm_free(m_pdata); _mm_free 是否允许 nullptr aka 0 作为 nop 像正常的 free 一样?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-11
    • 1970-01-01
    • 2017-06-01
    • 1970-01-01
    相关资源
    最近更新 更多