C++ g++;6.3,avx内部函数的Kahan求和用volatile关键字序列化

C++ g++;6.3,avx内部函数的Kahan求和用volatile关键字序列化,c++,g++,volatile,intrinsics,avx,C++,G++,Volatile,Intrinsics,Avx,使用avx intrinsics和Kahan求和算法,我尝试了这个(只是“加法器”的一部分): 没有错误,但当我检查反汇编(perf record,ubuntu中的report)时,它显示累加器、y和累加器错误变量的所有元素都是以标量方式逐个计算的 Q:如何定义一个内部变量,使其保持“操作顺序”,并且在内部指令中仍能使用(矢量化),而无需进行优化 为了确保它真的是标量,我删除了volatile,它变得更快了 有没有办法告诉gcc我需要一个变量/代码矢量化,但不需要触摸其他对象?如果您只想显式阻止

使用avx intrinsics和Kahan求和算法,我尝试了这个(只是“加法器”的一部分):

没有错误,但当我检查反汇编(perf record,ubuntu中的report)时,它显示累加器、y和累加器错误变量的所有元素都是以标量方式逐个计算的

Q:如何定义一个内部变量,使其保持“操作顺序”,并且在内部指令中仍能使用(矢量化),而无需进行优化

为了确保它真的是标量,我删除了volatile,它变得更快了


有没有办法告诉gcc我需要一个变量/代码矢量化,但不需要触摸其他对象?

如果您只想显式阻止关联数学优化,请不要使用
volatile
,而是使用函数属性禁用它们:

__attribute__ ((optimize("no-fast-math"))) 
inline void add(const __m256 &valuesToAdd) 
{
  __m256 y = _mm256_sub_ps(valuesToAdd, accumulatedError);
  __m256 t = _mm256_add_ps(accumulator, y);
  accumulatedError = _mm256_sub_ps(_mm256_sub_ps(t, accumulator), y);
  accumulator = t;
}

。使用编译标志和属性。此属性似乎不适用于clang(我想可能有类似的东西,但您的问题是针对g++的)。

如果您只想显式阻止关联数学优化,请不要使用
volatile
,而是使用函数属性禁用它们:

__attribute__ ((optimize("no-fast-math"))) 
inline void add(const __m256 &valuesToAdd) 
{
  __m256 y = _mm256_sub_ps(valuesToAdd, accumulatedError);
  __m256 t = _mm256_add_ps(accumulator, y);
  accumulatedError = _mm256_sub_ps(_mm256_sub_ps(t, accumulator), y);
  accumulator = t;
}

。使用编译标志和属性。这个属性似乎不适用于clang(我想可能有类似的东西,但您的问题是针对g++的)。

您想用
volatile
实现什么?防止局部变量被优化?你为什么需要这个
volatile
对于基于堆栈的局部变量没有任何好处。有了这个关键字,编译器显然将对每个浮点的访问视为一个单独的不同访问,假设它们在线性(非序列化)完成时可以在访问之间更改,所以AVX内部代码是用来模拟这种行为的。那么我唯一的选择就是使用内联asm来执行不改变顺序的操作?我不知道。我不明白你们想做什么,我用的是Kahan求和,减法和加法的顺序不能改变。Gcc不能改变asm块,但这比内部函数更难编码。我不能重复你的说法,即g++6.3使用
vaddss
指令而不是
vaddps ymm
对内部函数进行矢量化。相反,
volatile
的预期效果是,对于变量的每次读/写,强制实际加载/存储到内存中。对于
vaddps
/
vsubps
,Clang将重新加载到内存操作数中,但gcc使用单独的
vmovaps
指令。当然,当您删除
volatile
时,它会变得更快,但这不是因为标量!您想用
volatile
实现什么?防止局部变量被优化?你为什么需要这个
volatile
对于基于堆栈的局部变量没有任何好处。有了这个关键字,编译器显然将对每个浮点的访问视为一个单独的不同访问,假设它们在线性(非序列化)完成时可以在访问之间更改,所以AVX内部代码是用来模拟这种行为的。那么我唯一的选择就是使用内联asm来执行不改变顺序的操作?我不知道。我不明白你们想做什么,我用的是Kahan求和,减法和加法的顺序不能改变。Gcc不能改变asm块,但这比内部函数更难编码。我不能重复你的说法,即g++6.3使用
vaddss
指令而不是
vaddps ymm
对内部函数进行矢量化。相反,
volatile
的预期效果是,对于变量的每次读/写,强制实际加载/存储到内存中。对于
vaddps
/
vsubps
,Clang将重新加载到内存操作数中,但gcc使用单独的
vmovaps
指令。当然,当您删除
volatile
时,它会变得更快,但这不是因为标量!我将与内联汇编解决方案进行比较。如果性能相当,那么它只值得波音gcc。谢谢,我将与内联汇编解决方案进行比较。如果性能相当,那么它只值得波音gcc。非常感谢。