C++:英特尔 SIMD 内部函数类成员的初始化

Posted

技术标签:

【中文标题】C++:英特尔 SIMD 内部函数类成员的初始化【英文标题】:C++: initialization of intel SIMD intrinsics class members 【发布时间】:2014-04-14 21:42:51 【问题描述】:

我不明白为什么注释和未注释的行不会产生相同的结果(Linux GCC,启用了 C++11 标志):

#include "immintrin.h"


typedef __m256 floatv;

struct floatv2
public:

    //floatv2(const float f):x(_mm256_setzero_ps() + f ), y(_mm256_setzero_ps() + f ) ; // succeeds
    floatv2(const float f):x_mm256_setzero_ps() + f , y_mm256_setzero_ps() + f  ; // fails

//private:
    floatv x, y;
;

当尝试编译未注释的行时,我收到以下错误:

error: cannot convert ‘__m256 aka __vector(8) float’ to ‘float’ in initialization

我不明白,因为xy 是floatv,而不是float,所以不需要转换...

另外,在一些更复杂的代码中,第一个版本会产生内存访问冲突。幕后有什么不愉快的事情吗?

PS:上面__m256的定义,在avxintrin.h中有如下注释:

/* The Intel API is flexible enough that we must allow aliasing with other
   vector types, and their scalar components.  */

我不明白这是什么意思,但感觉可能是相关的:)

非常感谢

【问题讨论】:

Bug,请向gcc的bugzilla报告。 看起来像一个错误。顺便说一句,由于您已经在使用 _mm256_setzero_ps() ,因此没有理由添加 f,只需使用 _mm256_set1_ps()_mm256_broadcast_ps() 直接使用广播。以您的方式进行操作的唯一原因是您不必使用内在函数。定义__m256 zero= 并执行zero + f ***.com/questions/21727331/… 好点;我肯定会改用 _mm256_set1_ps(f) 。但是,使用 _mm256_set1_ps 时问题仍然存在。将向 GCC bugzilla 报告。非常感谢你们 【参考方案1】:

这与DR 1467 有关,它不允许使用列表初始化语法来复制聚合。这最近为 GCC 中的类修复,我将修复扩展到 r209449 中的向量。 Gcc-4.10 编译你的代码。

【讨论】:

【参考方案2】:

可能 _mm256_setzero_ps() + f 返回一个 float 而不是 floatv,因为 f 是一个 float。 因此,您不能使用 用浮点数初始化 floatv 值(x 和 y),因为 初始化不允许缩小(隐式转换)。

也许

xstatic_cast<__m256>(_mm256_setzero_ps() + f) 

会起作用的。

【讨论】:

嗨,很遗憾,这也失败了,x_mm256_set1_ps(f) 和 xstatic_cast<__m256>(_mm256_set1_ps(f)) 也失败了......

以上是关于C++:英特尔 SIMD 内部函数类成员的初始化的主要内容,如果未能解决你的问题,请参考以下文章

C++类成员冒号初始化以及构造函数内赋值

类对象作为成员

C++类的基本语法二(初始化列表友元static成员内部类)

C++类的基本语法二(初始化列表友元static成员内部类)

C++类的基本语法二(初始化列表友元static成员内部类)

c++ 初始化列表VS构造函数内赋值初始化成员变量