- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
在运行优化版代码(以NaN
和g++ 4.8.2
编译)时发现一个使一切变成4.9.3
的错误时,我确定问题出在-Ofast
选项,特别是它包括的-ffinite-math-only
标志。
该代码的一部分包括使用FILE*
从fscanf
读取浮点数,然后将所有NaN
替换为一个数值。但是,可以预料的是,-ffinite-math-only
进入并删除了这些检查,因此保留了NaN
。
在尝试解决此问题时,我偶然发现了this,它建议添加-fno-finite-math-only
作为方法属性来禁用特定方法的优化。以下内容说明了该问题以及尝试进行的修复(实际上并未修复):
#include <cstdio>
#include <cmath>
__attribute__((optimize("-fno-finite-math-only")))
void replaceNaN(float * arr, int size, float newValue){
for(int i = 0; i < size; i++) if (std::isnan(arr[i])) arr[i] = newValue;
}
int main(void){
const size_t cnt = 10;
float val[cnt];
for(int i = 0; i < cnt; i++) scanf("%f", val + i);
replaceNaN(val, cnt, -1.0f);
for(int i = 0; i < cnt; i++) printf("%f ", val[i]);
return 0;
}
echo 1 2 3 4 5 6 7 8 nan 10 | (g++ -ffinite-math-only test.cpp -o test && ./test)
进行编译/运行,该代码将无法正常工作,特别是,它会输出
nan
(应该已由
-1.0f
替换)-如果省略了
-ffinite-math-only
标志,它的行为会很好。这不行吗?我在gcc中缺少属性语法的某些东西吗,还是这是前面提到的“与此相关的某些版本的GCC出现问题”之一(来自链接的SO问题)
-fno-finite-math-only
(我的边缘解决方案)编译代码:我怀疑这种优化在程序的其余部分中对我的上下文可能非常有用。 "nan"
,然后在其中替换值(输入阅读器在库的无关部分中,因此在该测试中包含了较差的设计)。 isNaN
:我可以这样做,但这有点hackerable,不可移植。 -ffinite-math-only
标志的单独编译的程序对数据进行预过滤,然后将其输入到主程序中:维护两个二进制文件并使它们相互通信增加了复杂性,这是不值得的。 g++
较旧版本(例如
4.82
和
4.9.3
)中的编译器“错误”,而在较新版本(例如
5.1
和
6.1.1
)中已修复。
NaN
检查问题,那么可以选择另一种解决方案,如果可以确定该代码将始终在
IEEE754
浮点环境中运行,是为了手动检查
NaN
签名的浮点位。
g++
之间进行了更改,甚至拒绝遵守较早版本中的所需位置(
4.8.2
和
4.9.3
,始终将尾数放在首位),无论它们在代码中出现的顺序如何。
IEEE754
的编译器上使用。下面是我的这种实现,我最终将其用于解决我的问题。它检查
IEEE754
是否符合要求,并且我对其进行了扩展,以允许使用double以及其他更多常规的浮点位操作。
#include <limits> // IEEE754 compliance test
#include <type_traits> // enable_if
template<
typename T,
typename = typename std::enable_if<std::is_floating_point<T>::value>::type,
typename = typename std::enable_if<std::numeric_limits<T>::is_iec559>::type,
typename u_t = typename std::conditional<std::is_same<T, float>::value, uint32_t, uint64_t>::type
>
struct IEEE754 {
enum class WIDTH : size_t {
SIGN = 1,
EXPONENT = std::is_same<T, float>::value ? 8 : 11,
MANTISSA = std::is_same<T, float>::value ? 23 : 52
};
enum class MASK : u_t {
SIGN = (u_t)1 << (sizeof(u_t) * 8 - 1),
EXPONENT = ((~(u_t)0) << (size_t)WIDTH::MANTISSA) ^ (u_t)MASK::SIGN,
MANTISSA = (~(u_t)0) >> ((size_t)WIDTH::SIGN + (size_t)WIDTH::EXPONENT)
};
union {
T f;
u_t u;
};
IEEE754(T f) : f(f) {}
inline u_t sign() const { return u & (u_t)MASK::SIGN >> ((size_t)WIDTH::EXPONENT + (size_t)WIDTH::MANTISSA); }
inline u_t exponent() const { return u & (u_t)MASK::EXPONENT >> (size_t)WIDTH::MANTISSA; }
inline u_t mantissa() const { return u & (u_t)MASK::MANTISSA; }
inline bool isNan() const {
return (mantissa() != 0) && ((u & ((u_t)MASK::EXPONENT)) == (u_t)MASK::EXPONENT);
}
};
template<typename T>
inline IEEE754<T> toIEEE754(T val) { return IEEE754<T>(val); }
replaceNaN
函数变为:
void replaceNaN(float * arr, int size, float newValue){
for(int i = 0; i < size; i++)
if (toIEEE754(arr[i]).isNan()) arr[i] = newValue;
}
# In loop of replaceNaN
movl (%rcx), %eax # eax = arr[i]
testl $8388607, %eax # Check if mantissa is empty
je .L3 # If it is, it's not a nan (it's inf), continue loop
andl $2139095040, %eax # Mask leaves only exponent
cmpl $2139095040, %eax # Test if exponent is all 1s
jne .L3 # If it isn't, it's not a nan, so continue loop
最佳答案
对我来说似乎是一个编译器错误。从GCC 4.9.2开始,该属性被完全忽略。 GCC 5.1及更高版本对此予以注意。也许是时候升级您的编译器了?
__attribute__((optimize("-fno-finite-math-only")))
void replaceNaN(float * arr, int size, float newValue){
for(int i = 0; i < size; i++) if (std::isnan(arr[i])) arr[i] = newValue;
}
-ffinite-math-only
编译:
replaceNaN(float*, int, float):
rep ret
replaceNaN(float*, int, float):
test esi, esi
jle .L26
sub rsp, 8
call std::isnan(float) [clone .isra.0]
test al, al
je .L2
mov rax, rdi
and eax, 15
shr rax, 2
neg rax
and eax, 3
cmp eax, esi
cmova eax, esi
cmp esi, 6
jg .L28
mov eax, esi
.L5:
cmp eax, 1
movss DWORD PTR [rdi], xmm0
je .L16
cmp eax, 2
movss DWORD PTR [rdi+4], xmm0
je .L17
cmp eax, 3
movss DWORD PTR [rdi+8], xmm0
je .L18
cmp eax, 4
movss DWORD PTR [rdi+12], xmm0
je .L19
cmp eax, 5
movss DWORD PTR [rdi+16], xmm0
je .L20
movss DWORD PTR [rdi+20], xmm0
mov edx, 6
.L7:
cmp esi, eax
je .L2
.L6:
mov r9d, esi
lea r8d, [rsi-1]
mov r11d, eax
sub r9d, eax
lea ecx, [r9-4]
sub r8d, eax
shr ecx, 2
add ecx, 1
cmp r8d, 2
lea r10d, [0+rcx*4]
jbe .L9
movaps xmm1, xmm0
lea r8, [rdi+r11*4]
xor eax, eax
shufps xmm1, xmm1, 0
.L11:
add eax, 1
add r8, 16
movaps XMMWORD PTR [r8-16], xmm1
cmp ecx, eax
ja .L11
add edx, r10d
cmp r9d, r10d
je .L2
.L9:
movsx rax, edx
movss DWORD PTR [rdi+rax*4], xmm0
lea eax, [rdx+1]
cmp eax, esi
jge .L2
add edx, 2
cdqe
cmp esi, edx
movss DWORD PTR [rdi+rax*4], xmm0
jle .L2
movsx rdx, edx
movss DWORD PTR [rdi+rdx*4], xmm0
.L2:
add rsp, 8
.L26:
rep ret
.L28:
test eax, eax
jne .L5
xor edx, edx
jmp .L6
.L20:
mov edx, 5
jmp .L7
.L19:
mov edx, 4
jmp .L7
.L18:
mov edx, 3
jmp .L7
.L17:
mov edx, 2
jmp .L7
.L16:
mov edx, 1
jmp .L7
#pragma GCC push_options
#pragma GCC optimize ("-fno-finite-math-only")
void replaceNaN(float * arr, int size, float newValue){
for(int i = 0; i < size; i++) if (std::isnan(arr[i])) arr[i] = newValue;
}
#pragma GCC pop_options
-ffinite-math-only
开关的情况下,在GCC 5.1及更高版本上生成的代码仍然比编译函数差很多:
replaceNaN(float*, int, float):
test esi, esi
jle .L1
lea eax, [rsi-1]
lea rax, [rdi+4+rax*4]
.L5:
movss xmm1, DWORD PTR [rdi]
ucomiss xmm1, xmm1
jnp .L6
movss DWORD PTR [rdi], xmm0
.L6:
add rdi, 4
cmp rdi, rax
jne .L5
rep ret
.L1:
rep ret
std::isnan
的实现。如果此
replaceNaN
方法的速度不是至关重要的,则可能无关紧要。如果您需要重复地分析文件中的值,则可能更希望拥有一个相当有效的实现。
std::isnan
的非便携式实现。 IEEE 754格式都有很好的文档记录,并且假设您对代码进行了彻底的测试和注释,除非您确实需要将代码移植到所有不同的体系结构中,否则我看不到这样做的危害。它会驱使纯粹主义者陷入困境,但是应该使用
-ffinite-math-only
这样的非标准选项。对于
single-precision float,类似:
bool my_isnan(float value)
{
union IEEE754_Single
{
float f;
struct
{
#if BIG_ENDIAN
uint32_t sign : 1;
uint32_t exponent : 8;
uint32_t mantissa : 23;
#else
uint32_t mantissa : 23;
uint32_t exponent : 8;
uint32_t sign : 1;
#endif
} bits;
} u = { value };
// In the IEEE 754 representation, a float is NaN when
// the mantissa is non-zero, and the exponent is all ones
// (2^8 - 1 == 255).
return (u.bits.mantissa != 0) && (u.bits.exponent == 255);
}
my_isnan
而不是
std::isnan
即可。当启用
-ffinite-math-only
进行编译时,产生以下目标代码:
replaceNaN(float*, int, float):
test esi, esi
jle .L6
lea eax, [rsi-1]
lea rdx, [rdi+4+rax*4]
.L13:
mov eax, DWORD PTR [rdi] ; get original floating-point value
test eax, 8388607 ; test if mantissa != 0
je .L9
shr eax, 16 ; test if exponent has all bits set
and ax, 32640
cmp ax, 32640
jne .L9
movss DWORD PTR [rdi], xmm0 ; set newValue if original was NaN
.L9:
add rdi, 4
cmp rdx, rdi
jne .L13
rep ret
.L6:
rep ret
ucomiss
和随后的奇偶校验标志测试稍微复杂一些,但是只要您的编译器遵守IEEE 754标准,就可以保证NaN检查是正确的。这适用于所有版本的GCC和任何其他编译器。
关于c++ - 成功启用NaN移除方法上的-fno-finite-math-only,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38278300/
如上所述,我有一个转换图,但我不知道如何找到它的语言,在我看来有很多可能性,但我一定是误解了。我的理解是,任何从初始状态到最终状态的词都被接受。当然,有很多不同的方法可以实现这一目标。阿布,阿布,阿布
换句话说,我为什么要了解它?我什么时候要说...哦,我需要为此了解下推自动机或图灵机。 我看不到 Material 的应用。谢谢 最佳答案 您应该了解自动机理论,因为它会帮助您了解给定系统中的计算可能
哪个是确定两个自动机之间等价的最佳或最简单的方法? 即,如果给定两个有限自动机 A 和 B,我如何确定两者是否识别相同的语言? 它们都是确定性的或都是非确定性的。 最佳答案 一种不同的、更简单的方法是
我正在为我的计算理论课做作业,对如何组合 2 个 DFA 有点困惑。这本书说它使用“交叉结构”来做到这一点,但我不确定那是什么。这里有2个例子: 最佳答案 这个想法非常简单,尽管我可以看到混淆的地方。
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
我正在尝试证明这种语言是否: L = { w={0,1}* | #0(w) % 3 = 0 } (number of 0's is divisble by 3) 经常使用抽水引理,但我找不到办法。我得
我正在寻找一些有限自动机、下推自动机和图灵机任务示例的良好来源(用于手动解决)。 我四处寻找,但没有发现什么特别的东西,所以我想知道是否有人有一些很好的例子。提前致谢。 最佳答案 你最好的选择可能是买
嗯 - 问题说的是什么。这是我一直听说的事情,但我还没有时间去研究它。 (更新)我可以查找定义……但为什么不(正如@erikson 指出的那样)深入了解您的真实经历和轶事。 Community Wik
问题:构建一个只接受那些不以 ba 结尾的单词的 FA。我想为这个问题画 DFA,但我不明白我该怎么做,请帮我画这个 最佳答案 步骤: 绘制以“ba”结尾的 DFA。 反转状态即 做出最终状态,非最终
我有一个世界国家的 shapefile,从 here 下载.我可以在 R 中使用 countries <- readOGR("shp","TM_WORLD_BORDERS-0.3",encoding=
我现在正在上一门关于计算理论的类(class)。我能很好地理解这些概念。我可以解决问题。而且,当我问我的讲师关于真实世界的应用程序时,他告诉我这些概念在编译器设计中肯定有用且必不可少。但是,至少要进行
我必须使用 Streams API 从给定文件中找到所有最长的单词。我分几步完成,但寻找一些“一个衬里”,实际上我处理了整个文件两次,第一次是找到最大单词长度,第二次是将所有单词与最大长度进行比较,假
我已经将 is.finite() 用于向量、矩阵等,并且效果很好。我感到困惑的是为什么它似乎为数据框和列表返回 FALSE。 比如下面这个例子: m 具有非有限值的矩阵),我看不到 is.finit
我有一个 R 数据框 (df),如下所示: blogger; word; n; total joe; dorothy; 17; 718 paul; sheriff; 10; 354 joe; gray
在运行优化版代码(以NaN和g++ 4.8.2编译)时发现一个使一切变成4.9.3的错误时,我确定问题出在-Ofast选项,特别是它包括的-ffinite-math-only标志。 该代码的一部分包括
Locked. This question and its answers are locked,因为该问题是题外话,但具有历史意义。它目前不接受新的答案或互动。 有限状态机 确定性有限状态机是一种简
我目前正在尝试创建一个 R 函数来计算指定列与数据帧的所有数字列的 corr.test 相关性。这是我的代码: #function returning only numeric columns onl
在形式语言的乔姆斯基分类中,我需要一些 Non-Linear, Unambiguous and also Non-Deterministic 的例子上下文无关语言(N-CFL)? 线性语言 : 对于
早些时候,我在这里问了一个问题,寻求帮助将有限自动机的转换图转换为正则表达式: Understanding (and forming) the regular expression of this f
我正在使用 Julien Pilet 等人编写的开源代码。在标题为“使背景减法对突然的照明变化具有鲁棒性”下。我没有改变任何东西,只是运行它,然后它给了我以下错误: error C3861: 'fin
我是一名优秀的程序员,十分优秀!