Nếu bạn đang tìm kiếm một giá trị sẽ được nhân rộng bằng phép tính số học, NaN
vẫn có sẵn với tùy chọn -ffast-math
. Vấn đề nằm ở một nơi khác. Với -ffast-math
một số thao tác có thể bị xóa khỏi tính toán do tối ưu hóa, và sau đó không có cách nào để đảm bảo NaN
hoặc bất kỳ giá trị nào khác sẽ được truyền đi.
Ví dụ, sau đây, với -ffast-math
bộ, sẽ gây khó viết 0.0
vào n
và không có giá trị đặc biệt cho n
đó sẽ bảo vệ từ nó.
float n = NAN;
n *= 0.0;
Một điều bạn có thể làm, là sử dụng -fno-finite-math-only -ftrapping-math
với -ffast-math
như Shafik Yaghmour nói. Và khác là, nếu chỉ có vài nơi mà bạn mong đợi một giá trị xấu, bạn có thể tự kiểm tra nó bằng cách đặt các bài kiểm tra chính xác vào những điểm đó. Tùy chọn cuối cùng tôi có thể nghĩ - nếu bạn thực sự cần tối ưu hóa - là để tự chèn các giá trị NaN
(và có thể là inf
) vào tính toán và kiểm tra xem nó được lan truyền trong bao lâu. Sau đó, tại những nơi mà việc tuyên truyền dừng lại, hãy thử nghiệm cho sự xuất hiện của NaN
(inf
). - Đây là một phương pháp không an toàn, vì tôi không chắc chắn một trăm phần trăm, có thể -ffast-math
liên quan đến luồng điều kiện hoạt động. Nếu có thể, có một cơ hội đáng kể, giải pháp này sẽ không hợp lệ. Vì vậy, nó là nguy hiểm và nếu được lựa chọn cần thử nghiệm rất nặng bao gồm tất cả các chi nhánh của tính toán.
Thông thường tôi sẽ chống lại giải pháp cuối cùng, nhưng thực sự có một cơ hội, giá trị NaN
(inf
) sẽ được truyền đi mặc dù toàn bộ tính toán hoặc gần như toàn bộ, vì vậy nó có thể cung cấp hiệu suất bạn đang tìm kiếm. Vì vậy, bạn có thể muốn mạo hiểm.
Kiểm tra NaN
với -ffast-math
bạn có thể làm, như Shafik Yaghmour nói, với
inline int isnan(float f)
{
union { float f; uint32_t x; } u = { f };
return (u.x << 1) > 0xff000000u;
}
và cho double
với
inline int isnan(double d)
{
union { double d; uint64_t x; } u = { d };
return (u.x << 1) > 0xff70000000000000ull;
}
Kiểm tra inf
sẽ
inline int isinf(float f)
{
union { float f; uint32_t x; } u = { f };
return (u.x << 1) == 0xff000000u;
}
inline int isinf(double d)
{
union { double d; uint64_t x; } u = { d };
return (u.x << 1) == 0xff70000000000000ull;
}
Bạn cũng có thể hợp nhất isnan
và isinf
.
Chủ đề này có thể hữu ích [Mingw32 std :: isnan with -ffast-math] (http://stackoverflow.com/questions/7263404/mingw32-stdisnan-with-ffast-math) –
@ShafikYaghmour Cảm ơn, chủ đề đó là hữu ích. – stgtscc
Ngoài ra còn có tùy chọn sử dụng '-fno-finite-math-only -ftrapping-math' http://lua-users.org/lists/lua-l/2009-04/msg00091.html –