标签: x87

信号NaN的有用性?

我最近读了很多关于IEEE 754和x87架构的内容.我正在考虑在我正在研究的一些数值计算代码中使用NaN作为"缺失值",我希望使用信令 NaN将允许我在我不想要的情况下捕获浮点异常继续"缺失值".相反,我会使用安静的 NaN来允许"缺失值"通过计算传播.但是,信号NaN不起作用,因为我认为它们将基于它们上存在的(非常有限的)文档.

以下是我所知道的摘要(所有这些都使用x87和VC++):

  • _EM_INVALID(IEEE"无效"异常)在遇到NaN时控制x87的行为
  • 如果屏蔽了_EM_INVALID(禁用了异常),则不会生成异常,操作可以返回安静的NaN.涉及信令NaN的操作不会引发异常,但会转换为安静的NaN.
  • 如果_EM_INVALID未被屏蔽(启用了异常),则无效操作(例如,sqrt(-1))会导致抛出无效异常.
  • x87 从不生成信令NaN.
  • 如果_EM_INVALID是未屏蔽的,任何使用的信令的NaN(即使初始化与它的变量)的导致一个无效引发异常.

标准库提供了一种访问NaN值的方法:

std::numeric_limits<double>::signaling_NaN();
Run Code Online (Sandbox Code Playgroud)

std::numeric_limits<double>::quiet_NaN();
Run Code Online (Sandbox Code Playgroud)

问题是我认为信号NaN没有任何用处.如果屏蔽了_EM_INVALID,则其行为与安静NaN完全相同.由于没有NaN与任何其他NaN相当,因此没有逻辑差异.

如果屏蔽_EM_INVALID (启用异常),则甚至无法使用信号NaN初始化变量: double dVal = std::numeric_limits<double>::signaling_NaN();因为这会引发异常(信号NaN值被加载到x87寄存器以将其存储到存储器地址).

您可以像我一样思考以下内容:

  1. 掩码_EM_INVALID.
  2. 使用信令NaN初始化变量.
  3. Unmask_EM_INVALID.

但是,步骤2会导致信令NaN转换为安静的NaN,因此后续使用它不会导致异常被抛出!那么WTF?!

信号NaN是否有任何实用性或目的?我理解其中一个原始意图是使用它初始化内存,以便可以捕获使用单位化浮点值.

有人能告诉我,如果我在这里遗失了什么吗?


编辑:

为了进一步说明我希望做的事情,这里有一个例子:

考虑对数据向量(双精度)执行数学运算.对于某些操作,我想允许向量包含"缺失值"(假设这对应于电子表格列,例如,其中一些单元格没有值,但它们的存在很重要).对于某些操作,我希望允许向量包含"缺失值".如果集合中存在"缺失值",也许我想采取不同的行动 - 可能执行不同的操作(因此这不是无效的状态).

这个原始代码看起来像这样:

const double MISSING_VALUE = 1.3579246e123;
using std::vector;

vector<double> missingAllowed(1000000, MISSING_VALUE);
vector<double> missingNotAllowed(1000000, MISSING_VALUE);

// ... populate missingAllowed and missingNotAllowed with (user) data...

for (vector<double>::iterator it = missingAllowed.begin(); it != missingAllowed.end(); ++it) …
Run Code Online (Sandbox Code Playgroud)

c++ floating-point ieee-754 visual-c++ x87

50
推荐指数
1
解决办法
1万
查看次数

x87中的扩展(80位)双浮点,而不是SSE2 - 我们不会错过它?

我今天正在阅读研究人员发现NVidia的Phys-X库使用x87 FP与SSE2.显然,对于速度超过精度的并行数据集来说,这将是次优的.然而,文章作者继续引用:

英特尔在2000年末引入P4后开始不鼓励使用x87.AMD自2003年K8以来已弃用x87,因为x86-64定义为SSE2支持; VIA的C7自2005年以来一直支持SSE2.在64位版本的Windows中,x87不适用于用户模式,完全禁止在内核模式下使用.自2005年以来,业内所有人都推荐SSE超过x87,除非软件必须在嵌入式Pentium或486上运行,否则没有理由使用x87.

我想知道这件事.我知道x87内部使用80位扩展双精度值来计算值,而SSE2则不然.这对任何人都没关系吗?这对我来说似乎很惊讶.我知道当我对平面中的点,线和多边形进行计算时,在进行减法时,值可能出乎意料地错误,并且由于缺乏精度,区域可能会折叠并且线条会相互别名.我想,使用80位值与64位值可能会有所帮助.

这是不正确的?如果没有,如果x87被淘汰,我们可以用什么来执行扩展的双FP操作?

floating-point sse2 x87

35
推荐指数
2
解决办法
1万
查看次数

x87优于SSE的优点

我知道x87具有更高的内部精度,这可能是人们在它与SSE操作之间看到的最大差异.但我不得不怀疑,使用x87还有其他好处吗?我有-mfpmath=sse在任何项目中自动输入的习惯,我想知道我是否遗漏了x87 FPU提供的任何其他内容.

x86 sse x86-64 fpu x87

24
推荐指数
4
解决办法
6600
查看次数

由于更改了8087CW模式(Png + stretchblt),System.Move中的内存损坏

我有一个奇怪的内存损坏问题.经过几个小时的调试和尝试,我想我找到了一些东西.

例如:我做一个简单的字符串赋值:

sTest := 'SET LOCK_TIMEOUT ';
Run Code Online (Sandbox Code Playgroud)

但是,结果有时会变成:

sTest = 'SET LOCK'#0'TIMEOUT '
Run Code Online (Sandbox Code Playgroud)

所以,_被0字节取代.

我在System.Move函数中看到过这种情况发生一次(复制很棘手,取决于时间),当它使用FPU堆栈(fild,fistp)进行快速内存复制时(如果要移动9到32个字节):

...
@@SmallMove: {9..32 Byte Move}
fild    qword ptr [eax+ecx] {Load Last 8}
fild    qword ptr [eax] {Load First 8}
cmp     ecx, 8
jle     @@Small16
fild    qword ptr [eax+8] {Load Second 8}
cmp     ecx, 16
jle     @@Small24
fild    qword ptr [eax+16] {Load Third 8}
fistp   qword ptr [edx+16] {Save Third 8}
...
Run Code Online (Sandbox Code Playgroud)

使用FPU视图和2个内存调试视图(Delphi - > View - > Debug - > CPU - > Memory)我看到它出错...一次......无法重现......

今天早上我读到了关于8087CW模式的一些内容,是的,如果将其更改为$ …

delphi png stretchblt x87

24
推荐指数
1
解决办法
1499
查看次数

从FPU堆栈中删除内容的最简单方法

最近我在使用FPU堆栈溢出时遇到了一些麻烦.我设法将它追溯到一个错误的库函数,每次调用它时都会将垃圾值推送到FPU堆栈,并且永远不会清理它.

幸运的是,这很容易重现,我确切地知道它导致了什么条件.我可以将一行内联ASM放入调用此例程的例程中,将最高值从FPU堆栈中弹回...除了我不太清楚要写什么.我的ASM-fu对于middlin来说是公平的,但不是那么强大.

那么在x86汇编中摆脱FPU堆栈顶部值的最简单方法是什么,假设它是垃圾数据并且我不关心它的值?

x86 assembly x87

11
推荐指数
2
解决办法
5414
查看次数

SSE浮点运算是否可重复?

x87 FPU值得注意的是使用内部80位精度模式,这通常会导致编译器和机器出现意外和不可重现的结果.在我搜索 .NET上可重现的浮点数学时,我发现.NET(Microsoft和Mono)的两个主要实现都在64位模式下发出SSE指令而不是x87.

SSE(2)严格使用32位寄存器用于32位浮点数,严格使用64位寄存器用于64位浮点数.通过设置适当的控制字,可以选择将非正规数刷新为零.

因此,似乎SSE不会受到x87的精度相关问题的影响,并且唯一的变量是可以控制的非正规行为.

抛开超越函数的问题(SSE本身不像x87那样提供),是否使用SSE保证了机器和编译器之间可重现的结果?例如,编译器优化会转化为不同的结果吗?我发现了一些相互矛盾的观点:

如果您有SSE2,请使用它并从此过上幸福的生活.SSE2支持32b和64b操作,中间结果具有操作数的大小.- Yossi Kreinin,http://www.yosefk.com/blog/consistency-how-to-defeat-the-purpose-of-ieee-floating-point.html

...

SSE2指令(...)完全符合IEEE754-1985标准,它们具有更好的可重复性(由于静态舍入精度)和其他平台的可移植性.Muller et aliis, Handbook of Floating-Point Arithmetic - p.107

然而:

此外,您不能将SSE或SSE2用于浮点,因为它太低于指定而不具有确定性.- John Watte http://www.gamedev.net/topic/499435-floating-point-determinism/#entry4259411

.net floating-point sse ieee-754 x87

11
推荐指数
2
解决办法
2348
查看次数

为什么在Webkit运行时pow()计算错误?

我有一个Qt C++应用程序,其中有一个GUI线程,其中发生一些浮点计算.它还会打开QWebView一个带有一些视频的flash播放器.

很明显,关闭QWebView会干扰新的下一个浮点运算.因此pow(double, double)返回明确但不正确的值.

在一种情况下,它返回的值1000多于正确的值.另一次它返回1. #inf与参数一起使用时pow(10.0, 2.0).

我必须提到它是在不同的计算机上测试的,并不是特定于特定的CPU.

您是否有任何关于如何在Webkit中找到协处理器出错的地方以及如何防止它的建议?

样本(仅限x64)

环境:Qt 4.7.4,C++,HTML和flowplayer

CPP

wrongpow::wrongpow(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
 QVBoxLayout* layout = new QVBoxLayout(0);  
 m_view = new QWebView(this);  
 m_view->setMinimumSize(400, 400);
 m_view->settings()->setAttribute(QWebSettings::PluginsEnabled, true);
 m_view->settings()->setAttribute(QWebSettings::LocalContentCanAccessRemoteUrls, true);
 layout->addWidget(m_view);
 QDir dir(QApplication::applicationDirPath());
 dir.cd("media");
 m_view->load(QUrl(QFileInfo(dir, "index.html").absoluteFilePath()));

 QPushButton* button = new QPushButton(QLatin1String("Click on video start"), this);
 layout->addWidget(button);
 Q_ASSERT(connect(button, SIGNAL(clicked()), this, SLOT(closeView()))); 

 setLayout(layout);
 adjustSize();
}  
Q_SLOT void wrongpow::closeView()
{
 delete m_view;
 m_view = NULL;

 double wrongResult = …
Run Code Online (Sandbox Code Playgroud)

c++ qt webkit pow x87

11
推荐指数
1
解决办法
673
查看次数

在LLVM中调用fsincos指令比调用libc sin/cos函数要慢吗?

我正在研究用LLVM编译的语言.只是为了好玩,我想做一些微基准测试.其中一个,我在一个循环中运行了一百万个sin/cos计算.在伪代码中,它看起来像这样:

var x: Double = 0.0
for (i <- 0 to 100 000 000)
  x = sin(x)^2 + cos(x)^2
return x.toInteger
Run Code Online (Sandbox Code Playgroud)

如果我使用以下形式使用LLVM IR内联汇编来计算sin/cos:

%sc = call { double, double } asm "fsincos", "={st(1)},={st},1,~{dirflag},~{fpsr},~{flags}" (double %"res") nounwind
Run Code Online (Sandbox Code Playgroud)

这比分别使用fsin和fcos而不是fsincos更快.但是,它比我分别调用llvm.sin.f64and llvm.cos.f64intrinsics,编译调用C math lib函数要慢,至少使用我正在使用的目标设置(x86_64启用了SSE).

似乎LLVM在单/双精度FP之间插入一些转换 - 这可能是罪魁祸首.这是为什么?对不起,我是大会上的新手:

    .globl  main
    .align  16, 0x90
    .type   main,@function
main:                                   # @main
    .cfi_startproc
# BB#0:                                 # %loopEntry1
    xorps   %xmm0, %xmm0
    movl    $-1, %eax
    jmp     .LBB44_1
    .align  16, 0x90
.LBB44_2:                               # %then4
                                    #   in Loop: Header=BB44_1 Depth=1 …
Run Code Online (Sandbox Code Playgroud)

assembly llvm inline-assembly x87

10
推荐指数
1
解决办法
3740
查看次数

为什么这个使用 gcc、-mfpmath=387 和优化级别 -O2 或 -O3 编译的简单程序会产生 NaN 值?

我有一个简短的程序,它执行数值计算,并在某些特定条件成立时获得不正确的 NaN 结果。我看不出这个 NaN 结果是如何产生的。请注意,我没有使用允许重新排序算术运算的编译器选项,例如-ffath-math.

\n

问题:我正在寻找 NaN 结果如何产生的解释。从数学上讲,计算中没有任何内容会导致除以零或类似的结果。我错过了一些明显的东西吗?

\n

请注意,我不是问如何解决问题\xe2\x80\x94,这很简单。我只是想了解 NaN 是如何出现的。

\n

最小的例子

\n

请注意,这个示例非常脆弱,甚至需要进行很小的修改,例如添加printf()在循环中添加调用以观察值)也会改变行为。这就是为什么我无法进一步减少它。

\n
// prog.c\n\n#include <stdio.h>\n#include <math.h>\n\ntypedef long long myint;\n\nvoid fun(const myint n, double *result) {\n    double z = -1.0;\n    double phi = 0.0;\n    for (myint i = 0; i < n; i++) {\n        double r = sqrt(1 - z*z);\n\n        /* avoids division by zero when r == 0 */\n        if (i != 0 && i != n-1) {\n            phi …
Run Code Online (Sandbox Code Playgroud)

c floating-point x86 gcc x87

10
推荐指数
2
解决办法
417
查看次数

如何使用内联汇编指定直接浮点数?

当我尝试编译此代码时:

#include <stdio.h>

main(int argc, char *argv[]) {
   double y = 0;

   __asm__ ("fldl $150;"
            "fsqrt;"
            "fstl %0;" : : "g" (y) );

   printf("%f\n", y);


   return 0;
}
Run Code Online (Sandbox Code Playgroud)

我收到此错误:

sqrt.c: Assembler messages:
sqrt.c:6: Error: suffix or operands invalid for `fld'
Run Code Online (Sandbox Code Playgroud)

为什么这不起作用?为什么我不能将数字"150"推入堆栈进行浮点运算?

c assembly gcc inline-assembly x87

9
推荐指数
2
解决办法
6364
查看次数

标签 统计

x87 ×10

floating-point ×4

assembly ×3

x86 ×3

c ×2

c++ ×2

gcc ×2

ieee-754 ×2

inline-assembly ×2

sse ×2

.net ×1

delphi ×1

fpu ×1

llvm ×1

png ×1

pow ×1

qt ×1

sse2 ×1

stretchblt ×1

visual-c++ ×1

webkit ×1

x86-64 ×1