gpt4 book ai didi

c - C 多线程环境中的浮点损坏

转载 作者:太空宇宙 更新时间:2023-11-03 23:32:49 25 4
gpt4 key购买 nike

加法和乘法返回的浮点值最终无效,我遇到了问题。

背景:我在 Visual Studio 多线程环境中使用 Speex。在某个时刻,通常经过 1 或 2 分钟的音频编码和解码后,我的解码信号完全变成了 Nan。我认为我的问题与此线程 ( Speex on windows, audio cutting out ) 中讨论的问题相同,但我在这个问题上进行了更深入的研究。

情况:我修改了一部分 libspeex 以放置一些调试代码,这就是我所拥有的(我在这里扩展了一些宏,我知道有些部分是多余的)。

float *mem, *den;     // Arrays of finite float values
float nyi; // finite float value.
float a1, a2; // debug test variables.

...

if (!_finite(mem[j]) || !_finite(mem[j+1]))
printf("Nan\n"); // Does not reach this

a1 = ((mem[j+1])+(float)(den[j])*(float)(nyi)); // a1 == expected value
mem[j] = ((mem[j+1])+(float)(den[j])*(float)(nyi)); // mem[j] == -1.#IND
a2 = ((mem[j+1])+(float)(den[j])*(float)(nyi)); // a2 == expected value

if (!_finite(mem[j]) || !_finite(mem[j+1]))
printf("Nan\n"); // Program reach this and stops at breakpoint

第一个奇怪的行为是 a1a2 计算出正确的值,而 mem[j] 却没有。第二件奇怪的事情:如果我尝试重新执行 affectation to mem[j] 语句(我知道这可能会导致意想不到的结果,但它仍然给出调试目的的提示),那么值影响mem[j]的是期望值:同a1和a2。

我确实检查了明显的:

  • 此代码部分受互斥锁保护:其他线程不可能损坏内存。
  • 所有的浮点值都是有效的、有限的,加法和乘法的结果应该落在 float ​​的范围内。
  • 所有数组索引都在各自数组的范围内。

如果没有其他线程在运行,问题似乎不会出现。

  • 本线程:音频解码线程。
  • 一个音频编码线程。
  • 一些网络套接字线程...

它是大型软件的一部分,但解码部分确实受到适当互斥体的保护。

所以看起来好像在浮点计算的中间发生了上下文切换,并且之后无法恢复上下文。但很难相信会发生这么糟糕的事情。

我听说在多线程中使用 float 不一致,但它应该只影响最低有效部分,不会生成 Nan 值。

有没有人见过这样的行为?你是怎么解决的?

最佳答案

问题:

  • 所有多余的转换是怎么回事?
  • den[j]nyi 的值是多少?

除此之外,一个合理的可能性是同一线程上的另一个计算已经溢出浮点堆栈,或者使用了 MMX 指令但未能在产生控制之前发出 emms 指令(无论是这些条件将导致无可争议的浮点计算产生 NaN 结果)。首先检查处于故障状态的 x87 状态字,以确认或排除这些可能性。

没有多线程就不会出现问题的事实使得这种解释不太可能,但损坏的 x87 状态是迄今为止“无法解释的”NaN 的最常见来源,应该首先排除。

关于c - C 多线程环境中的浮点损坏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11689172/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com