2013-07-12 18 views
10

Kể từ khi lựa chọn gcc-ffast-math thể vô hiệu hóa NaN-/+inf, tôi đang tìm có thể là lựa chọn tốt nhất tiếp theo cho đại diện NaN trong mã toán hiệu suất quan trọng của tôi. Lý tưởng nhất là giá trị sentinel nếu hoạt động trên (thêm, mul, div, sub, vv ..) sẽ mang lại giá trị sentinel như NaN sẽ làm nhưng tôi nghi ngờ điều này sẽ có thể vì tôi nghĩ rằng NaN là giá trị duy nhất thực hiện điều này. -0.0 có thể không phù hợp như nó cũng vô hiệu hóa trong -ffast-math và có thể ngăn chặn tối ưu hóa nhất định như (x+0.0), vv ..giá trị sentinel Tốt cho đôi nếu thích sử dụng -ffast-toán

Có lẽ câu hỏi của tôi chứ không nên, là có cách nào để sử dụng NaN hoặc một số khác "đặc biệt đôi" trong khi có thể kích hoạt nhiều tối ưu hóa toán học mà không bị hỏng?

Hệ thống là Linux/x64, gcc 4.8.1.

+4

Chủ đề này có thể hữu ích [Mingw32 std :: isnan with -ffast-math] (http://stackoverflow.com/questions/7263404/mingw32-stdisnan-with-ffast-math) –

+0

@ShafikYaghmour Cảm ơn, chủ đề đó là hữu ích. – stgtscc

+2

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 –

Trả lời

4

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 isnanisinf.

Các vấn đề liên quan