我学习openMP并且凭借我有限的知识,将我的代码平行化了。我试图使用openMP矢量化技术改进此代码。但是在浏览相关阅读材料(link)时,我发现不可能对long double数据类型进行矢量化操作。有人可以提供有关其原因的信息,并建议除降低精度之外的解决方案吗?
链接中的内容如下:"避免SIMD硬件中不支持的操作。在Linux上,(80位)长的算术加倍,而余数运算符“%”是SIMD硬件中不支持的操作的示例。 "
P.S。我使用INTEL C ++编译器16.0.2,INTEL XEON processsor和128位长矢量寄存器和Linux。我的数据类型大多是long double。
答案 0 :(得分:3)
x86指令集的SIMD指令仅支持32位和64位浮点运算(对16位浮点数的支持有限)。另外,即使有64位乘以64位到128位的标量整数指令(例如mulx
),也没有相应的SIMD指令。许多人尝试过并且未能实现有效的128位整数x86 SIMD算法(multiplication和addition有一些例外)。没有通用的x86 SIMD整数除法指令。
然而,对于浮点数,使用double-double的高精度浮点SIMD操作取得了更大的成功。双精度具有106位精度,而64位精度具有80位长双精度。但并非每个C ++编译器都使用80位长的double。有些只使用双精度(例如MSVC),它只有54位精度,有些使用128位四精度,精度为113位,维基百科甚至声称,对于某些编译器,long double实现为double-double。
我描述了双重here的一些细节。请注意,double-double不是IEEE浮点类型,它具有一些不寻常的属性。此外,double-double的范围与double相同,因此只提高了精度。
与双倍相比,双倍的速度有多快?我从未测试过这个。但是我发现,在进行乘法和加法运算的平衡混合时,双倍运算要比双运算慢10倍。 long double肯定比double慢(除非它被实现为double)。但是既然你可以使用双倍的SIMD,但不能使用内置的长双倍,那么速度会随着SIMD宽度的增加而提高。所以2个双重操作SSE2,4个AVX,8个AVX512。
不要期望OpenMP的simd
构建实现两倍。您需要自己实现或找到一个库。