英特尔® 至强® 处理器和英特尔® 至强融核™ 协处理器的浮点算法差异

下载文章

下载英特尔® 至强® 处理器和英特尔® 至强融核™ 协处理器的浮点算法差异 [PDF 167KB]

本文介绍英特尔® 编译器使用的浮点模型及其在英特尔® 至强® 处理器场景中的应用“英特尔® 编译器浮点运算结果的一致性”。 在正确设置的情况下,编译器生成的代码完全符合面向二进制浮点算法的 ANSI 语言标准和 IEEE-754 标准。 编译器选项支持用户合理控制性能优化、精确度、结果再现性和标准合规性。

这一浮点模型还适用于英特尔® 至强融核™ 协处理器,但是与英特尔至强处理器之间的结构差异导致实施过程有所不同。 本文主要讨论这些差别。

基础知识

英特尔至强融核协处理器和英特尔至强处理器支持的浮点数据类型相同。 单精度(32 位)和双精度(64 位)由硬件支持;四倍精度(128 位)由软件支持。 扩展精度(80 位)由 x87 指令集支持。 支持非正态化数字和逐渐下溢;但是所有优化级别(-O0)的默认设置是突然下溢。 支持的舍入模式和英特尔至强处理器相同。

浮点例外

最大差异体现在浮点例外的处理。 英特尔至强融核协处理器上的矢量浮点单元会做标记,但是不捕获浮点例外。 VXCSR 寄存器中对应的位受到保护;修改它会导致分段错误。 英特尔集成众核架构(英特尔® MIC 架构)不支持特定编译器选项,如 -fp-trap (C/C++) 或 -fpe0 (Fortran),这些选项会捕获英特尔至强处理器上的浮点例外。

-fp-model except 或 -fp-model strict 等选项还要求面向浮点例外的严格、标准语义。 因此需要为浮点运算生成 x87 代码而非利用英特尔® 集成众核指令(英特尔® IMCI)的代码。 由于这些代码无法矢量化,因此会严重影响性能。 然而,这些选项有助于排查应用的故障。 同理,-ansi 和 -fmath-errno 选项可能导致调用使用 x87 而非英特尔® IMCI 实施的数学函数。

在 Fortran 编译器 13.0 中,IEEE_FEATURES、IEEE_ARITHMETIC 和 IEEE_EXCEPTIONS 模块尚未针对英特尔至强融核协处理器的特性进行更新。

-fp-model switch

与英特尔至强处理器一样支持同一 -fp-model switch 模式设置。 默认设置都是 -fp-model fast=1。 尽管对英特尔至强融核协处理器的性能影响更大,但是 -fp-model precise 选项的表现相同,这是因为英特尔集成众核架构的矢量带宽更大,约分循环矢量化的潜在性能优势更大,以及循环包含了超越数学函数、平方根或除法运算。 由于上述原因,-fp-model except 和 -fp-model strict 对性能的影响更大。

-fp-model fast=2 设置 -fimf-domain-exclusion switch,并为英特尔至强融核协处理器支持速度更快的内联数学函数。请参考下文“数学函数精度”。

-fp-model precise switch 支持算法使用非正态化的数字并禁用突然下溢;突然[逐渐]下溢可直接使用 -[no-]ftz 支持(但非强制要求)。 表现和英特尔至强处理器相同。

乘加融合指令

英特尔至强处理器直至第三代英特尔® 酷睿™ 处理器不支持乘加融合(FMA)指令。 英特尔至强融核协处理器的 FMA 指令仅对最终结果执行单次舍入,因此和独立加乘指令的结果差别不大。

原则上,-fp-model strict switch 会禁用乘加融合(FMA)指令。 但是如上所述,-fp-model strict 影响英特尔® IMCI 偏爱传统 x87 浮点指令,这一附加表现没有实际意义。 默认状态下启用乘加融合(FMA)指令运算,但可通过 switch -no-fma 禁用。 FMA 运算不可通过 -fp-model precise 禁用。

数学函数精度

在英特尔® Composer XE 2013 产品中,默认状态下,面向英特尔至强融核协处理器的编译器为标量和矢量代码提供中等精度的(< 4 ulp)超越函数,一般调用 libsvml。 对于英特尔至强处理器,默认状态下,标量代码的精度为 libm (< 0.55 ulp),矢量代码的精度为中等 libsvml (< 4 ulp)。 对于英特尔至强融核协处理器,除法默认为使用倒数指令的中等精度内联代码,而对于初始 13.0 编译器版本,平方根默认状态下调用中等精度 SVML 函数(在未来更新版本中将变为内联代码)。 如需获取平方根的内联版本,可通过

-fimf-domain-exclusion=15:sqrt (双精度)或 -fimf-domain-exclusion=15:sqrt (单精度)。 参看编译器文档了解相关内容。 还可使用 -fimf-domain-exclusion switch 获取其它特定数学函数的内联版本。 高精度(通常 0.6 ulp)、可矢量化的 SVML 版本的除法、平方根和超越函数可通过 -fimf-precision=high 获取。

-fp-model precise 提供高精度(<0.55 ulp),标量代码为超越函数调用 libm,为平方根调用 libsvml。 对于除法,需要 x87 除法指令。 -no-fast- transcendentals、-prec-sqrt 和 -prec-div 具有同样的表现。 在未来更新中,对于这些交换函数,使用英特尔® IMCI 的矢量化内联代码队列可能用于除法和平方根而非使用 x87 指令;对于 -fp-model precise,x87 指令将继续为 -fp-model strict 生成。

通过指明 -fp-model precise、-fast-transcendentals 或 -no-prec-sqrt -no-prec-div,可获取中等精度矢量化数学函数以及 -fp-model precise。 更高精度的矢量化版本可通过添加 -fimf-precision=high 获得。

英特尔至强融核协处理器和英特尔至强处理器的浮点运算结果比较

尽管英特尔至强融核协处理器和英特尔至强处理器的底层硬件指令基于同样标准,但是二者的浮点计算结果并非是位对位一致的。 编译器优化的实施方法可能不同,数学函数的实施方法可能不同,等等。英特尔至强融核协处理器可用的乘加融合(FMA)指令是存在差异的通用源。 不过,以下指南有助于为不同平台减小差异,不过性能会受影响。

使用 -fp-model precise -fp-model source 在两大平台上构建应用。

使用 -no-fma 在英特尔至强融核协处理器平台上构建应用,并禁用乘加融合指令。 [或者(仅对于 Fortran 应用),您可使用括弧语句限制单个表达中的 fma 指令,结合使用命令行交换 -assume protect_parens,例如: X = (A + (B*C)) ]。 对于 C 或 C++ 应用,您可使用 #pragma fp_contract (off | on) 禁用每个函数中的 FMA 生成。

为两个平台选择高精度数学函数,例如,使用 -fimf-precision=high。

对于并行执行约分的 OpenMP 应用,环境参数设置为 KMP_DETERMINISTIC_REDUCTIONS=yes,使用静态调度,使用 OMP_NUM_THREADS 将每个平台的线程数量设置为相等。

对于采用英特尔® 线程构建模块(英特尔® TBB)的 C++ 应用,可使用 parallel_deterministic_reduction() function 获取更加一致性的结果,即使平台的线程数量不同。

这些指南旨在增强再现性并缩小不同平台浮点计算结果的差异。 观察到的差异并不代表您的计算结果的真正不确定性,实际数值可能更大。

英特尔、Intel 标识、Vtune、融核、Phi、至强和 Xeon 是英特尔公司在美国和其他国家(地区)的商标。

* 其他的名称和品牌可能是其他所有者的财产。

英特尔公司 © 2013 年版权所有。 所有权保留。

性能声明

关于性能及基准数据的更完整的信息,敬请登陆:www.intel.com/benchmarks

有关编译器优化的更完整信息,请参阅优化通知