- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
考虑这个简单的代码:
#include <complex.h>
complex float f(complex float x) {
return x*x;
}
如果您使用英特尔编译器使用 -O3 -march=core-avx2 -fp-model strict
编译它,您将获得:
f:
vmovsldup xmm1, xmm0 #3.12
vmovshdup xmm2, xmm0 #3.12
vshufps xmm3, xmm0, xmm0, 177 #3.12
vmulps xmm4, xmm1, xmm0 #3.12
vmulps xmm5, xmm2, xmm3 #3.12
vaddsubps xmm0, xmm4, xmm5 #3.12
ret
这比您从 gcc
和 clang
获得的代码简单得多,也比您在网上找到的复数乘法代码简单得多。例如,它不会明确地处理复杂的 NaN 或无穷大。
Does this assembly meet the specs for C99 complex multiplication?
最佳答案
代码不符合规范。
附件 G,第 5.1 节,第 4 段阅读
The
*
and/
operators satisfy the following infinity properties for all real, imaginary, and complex operands:— if one operand is an infinity and the other operand is a nonzero finite number or an infinity, then the result of the * operator is an infinity;
所以如果 z = a * ib 是无限的并且 w = c * id 是无限的,数 z * w 必须是无限的。
同一附件第 3 节第 1 段定义了无限复数的含义:
A complex or imaginary value with at least one infinite part is regarded as an infinity (even if its other part is a NaN).
所以 z 是无限的,如果 a 或 b 是无限的。
这确实是一个明智的选择,因为它反射(reflect)了数学框架1。
然而,如果我们让 z = ∞ + i∞(无限值)并且 w = i ∞(和无限值)英特尔代码的结果是 z * w = NaN + iNaN 由于 ∞ · 0 中间体<支持>2.
这足以将其标记为不合格。
我们可以通过查看第一个引用的脚注(此处未报告脚注)进一步确认这一点,它提到了 CX_LIMITED_RANGE
pragma 指令。
Section 7.3.4, Paragraph reads
The usual mathematical formulas for complex multiply, divide, and absolute value are problematic because of their treatment of infinities and because of undue overflow and underflow. The
CX_LIMITED_RANGE
pragma can be used to inform the implementation that (where the state is ‘‘on’’) the usual mathematical formulas [that produces NaNs] are acceptable.
标准委员会正在努力减轻复杂乘法(和除法)的巨大工作量。
In fact GCC has a flag to control this behaviour :
-fcx-limited-range
When enabled, this option states that a range reduction step is not needed when performing complex division.Also, there is no checking whether the result of a complex multiplication or division is NaN + I*NaN, with an attempt to rescue the situation in that case.
The default is
-fno-cx-limited-range
, but is enabled by-ffast-math
.
This option controls the default setting of the ISO C99CX_LIMITED_RANGE
pragma.
仅此选项即makes GCC generate slow code and additional checks , 没有它,它生成的代码具有与英特尔代码相同的缺陷(我将源代码翻译成 C++)
f(std::complex<float>):
movq QWORD PTR [rsp-8], xmm0
movss xmm0, DWORD PTR [rsp-8]
movss xmm2, DWORD PTR [rsp-4]
movaps xmm1, xmm0
movaps xmm3, xmm2
mulss xmm1, xmm0
mulss xmm3, xmm2
mulss xmm0, xmm2
subss xmm1, xmm3
addss xmm0, xmm0
movss DWORD PTR [rsp-16], xmm1
movss DWORD PTR [rsp-12], xmm0
movq xmm0, QWORD PTR [rsp-16]
ret
没有它代码是
f(std::complex<float>):
sub rsp, 40
movq QWORD PTR [rsp+24], xmm0
movss xmm3, DWORD PTR [rsp+28]
movss xmm2, DWORD PTR [rsp+24]
movaps xmm1, xmm3
movaps xmm0, xmm2
call __mulsc3
movq QWORD PTR [rsp+16], xmm0
movss xmm0, DWORD PTR [rsp+16]
movss DWORD PTR [rsp+8], xmm0
movss xmm0, DWORD PTR [rsp+20]
movss DWORD PTR [rsp+12], xmm0
movq xmm0, QWORD PTR [rsp+8]
add rsp, 40
ret
和 __mulsc3
function实际上与标准 C99 推荐的复数乘法相同。
它包括上述检查。
1 其中一个数的模数是从实际情况 |z| 扩展而来的到复数 ‖z‖,由于无界限制而保持无限的定义。简单地说,在复平面上有一整圆的无限值,只需一个“坐标”无限就可以得到无限模。
2 如果我们记住 z = NaN + i∞ 或 z = ∞,情况会变得更糟+ iNaN 是有效的无限值
关于c - ICC 是否满足复数乘法的 C99 规范?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42045291/
我没有 icc已安装,但我需要所有编译器优化标志的列表。我试过谷歌并搜索他们的网站文档,但我找不到任何东西。 我找到了一个列表 all编译器选项,但我只需要优化选项。 最佳答案 此页面列出了 IC 优
我使用的是 ubuntu 14.04。我刚刚下载并安装了英特尔并行工作室 2016。 如果我不是从 icc 文件夹中输入 icc,则会收到错误命令未找到。有没有办法像 gcc 一样设置 icc(在我运
我最近开始使用 ICC (18.0.1.126) 来编译一段代码,该代码可以在任意优化设置上与 GCC 和 Clang 一起正常工作。该代码包含一个汇编例程,该例程使用 AVX2 和 FMA 指令将
我的问题是我想从命令行调用 icc 编译器,但我的电脑找不到它。我已经安装了最新的 oneAPI 并获取了 setvars.sh。 即使我在安装例程下搜索'icc'文件我也找不到icc编译器文件。 '
使用 ICC 编译时,每条指令后面都是 2 个点分隔的数字,并以哈希符号为前缀。这是什么意思? For example: L__routine_start__Z12testFunctionPii_0:
有人可以解释为什么 icc 在下面的代码 1 中没有执行循环不变代码运动(移动 a 的指针赋值)的原因。当 a 指针赋值从代码 2 中完成的 t6 循环中移出时,我看到性能提高了 40%。我尝试将指针
考虑以下代码: template struct Foo { }; template struct Foo> { static void print() { std::cerr s
我在 Visual Studio 2012 中使用 Intel C++ 13.0.1.119 Build 20121008 for IA-32 在 Windows 上运行。我一直遇到链接器错误问题,并
我一直在尝试使用英特尔的四精度 float 。我有以下代码,它返回了意外的结果。 #include #include int print(const char *label, _Quad r) {
我写了一个应用程序,它通过 ImageMagick 修剪和调整一堆图像的大小。图像也被转换为灰度。但是当我尝试在 Photoshop CC 中打开转换后的图像时,会出现以下警告: The embedd
我正在用 icc 编译一个 cpp 代码(在 ubuntu 下): icc -I/usr/share/R/include -I/~/Desktop/work/p1/geqw4/vi3/out/sp/c
首先让我说我是 R 的新手,并试图弄清楚如何在我的特定数据集上运行 icc,这可能与正常情况下有点不同。 数据集如下所示 +------------+------------------+------
我遇到了 icc 问题,到目前为止我还没有找到任何解决方案。我的程序用gcc编译时运行正常,但用icc编译时显然没有执行任何操作。不会发生运行时错误。该程序结束得非常快(几毫秒),但预计需要几秒钟(对
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 7年前关闭。 Improve thi
在尝试使用 Jasper Reports 生成符合 PDF/A 标准的 PDF 时,我得到了 net.sf.jasperreports.engine.util.JRPdfaIccProfileNotF
因此,当使用基本的icc bob.cpp -o bob 编译并运行时,出现以下代码段错误: #include int foo () { return 6; } int main() { st
现在我正在使用 icc 来编译和运行我的 ANSI C 代码。 当我打开-O2 优化时,一切正常。但是,当我更改为 -fast 时,结果会有所不同(有很多 nan)。 我搜索并尝试,发现错误存在于-x
我想报告一个有趣的错误。下面的这段代码应该打印出 20 次“1.0”。相反,在我的 mac(雪豹 10.6.8)上使用 icc(11.1)编译时,我得到不稳定的值(16 次“0.0”然后 4 次“1.
有没有办法在使用英特尔编译器时改变缓存写入策略。我发现 Intel Core i7 处理器的一级缓存是回写缓存。 我的问题是:是否有任何可能的方法来调整编译器,将缓存策略从回写更改为直写? 最佳答案
我目前在 centos7 上校准显示器时遇到问题。使用 gnome 或 kde,我无法正确使用颜色设置来应用新创建的 ICC 配置文件。设备选项卡未显示列出(仅安装了打印机)。 经过一些阅读,我发现
我是一名优秀的程序员,十分优秀!