Ffast-math thực sự làm gì?


144

Tôi hiểu --ffast-mathcờ của gcc có thể tăng tốc độ đáng kể cho phao nổi và vượt ra ngoài các tiêu chuẩn của IEEE, nhưng dường như tôi không thể tìm thấy thông tin về những gì đang thực sự xảy ra khi nó diễn ra. Bất cứ ai cũng có thể vui lòng giải thích một số chi tiết và có thể đưa ra một ví dụ rõ ràng về cách một cái gì đó sẽ thay đổi nếu cờ bật hoặc tắt?

Tôi đã thử đào qua SO cho các câu hỏi tương tự nhưng không thể tìm thấy bất cứ điều gì giải thích hoạt động của toán học ffast.

Câu trả lời:


86

Như bạn đã đề cập, nó cho phép tối ưu hóa không duy trì sự tuân thủ nghiêm ngặt của IEEE.

Một ví dụ là:

x = x*x*x*x*x*x*x*x;

đến

x *= x;
x *= x;
x *= x;

Bởi vì số học dấu phẩy động không liên quan, nên thứ tự và bao thanh toán của các hoạt động sẽ ảnh hưởng đến kết quả do làm tròn số. Do đó, việc tối ưu hóa này không được thực hiện theo hành vi nghiêm ngặt của FP.

Tôi thực sự chưa kiểm tra xem GCC có thực sự tối ưu hóa cụ thể này không. Nhưng ý tưởng là như nhau.


25
@Andrey: Ví dụ này, bạn đi từ 7 nhân xuống còn 3.
Bí ẩn

4
@Andrey: Về mặt toán học, nó sẽ đúng. Nhưng kết quả có thể hơi khác nhau trong một vài bit cuối do cách làm tròn khác nhau.
Bí ẩn

1
Trong hầu hết các trường hợp, sự khác biệt nhỏ này sẽ không thành vấn đề (tương đối theo thứ tự 10 ^ -16 cho double, nhưng thay đổi tùy thuộc vào ứng dụng). Một điều cần lưu ý là tối ưu hóa toán học nhanh không nhất thiết phải thêm "vòng" nữa. Lý do duy nhất khiến nó không tuân thủ theo chuẩn IEEE là vì câu trả lời khác (dù chỉ một chút) so với những gì được viết.
Bí ẩn

1
@user: Độ lớn của lỗi phụ thuộc vào dữ liệu đầu vào. Nó nên nhỏ so với kết quả. Ví dụ: nếu xnhỏ hơn 10, lỗi trong ví dụ của Mystical sẽ giảm xuống khoảng 10 ^ -10. Nhưng nếu x = 10e20, lỗi có thể là nhiều triệu.
Ben Voigt

3
@stefanct nó thực sự về -fassociative-mathđược bao gồm trong -funsafe-math-optimizationsđó lần lượt được kích hoạt với -ffast-math Tại sao không GCC tối ưu hóa a*a*a*a*a*ađể (a*a*a)*(a*a*a)?
phuclv

255

-ffast-math làm được nhiều hơn là chỉ phá vỡ sự tuân thủ nghiêm ngặt của IEEE.

Tất nhiên, trước hết, nó phá vỡ sự tuân thủ nghiêm ngặt của IEEE, cho phép ví dụ sắp xếp lại các hướng dẫn cho một cái gì đó giống nhau về mặt toán học (lý tưởng) nhưng không hoàn toàn giống nhau ở điểm nổi.

Thứ hai, nó vô hiệu hóa cài đặt errnosau các hàm toán học một lệnh, có nghĩa là tránh ghi vào biến cục bộ của luồng (điều này có thể tạo ra sự khác biệt 100% cho các hàm đó trên một số kiến ​​trúc).

Thứ ba, nó đưa ra giả định rằng tất cả toán học là hữu hạn , điều đó có nghĩa là không có kiểm tra nào đối với NaN (hoặc không) được thực hiện tại nơi chúng sẽ có tác động bất lợi. Nó chỉ đơn giản là giả định rằng điều này sẽ không xảy ra.

Thứ tư, nó cho phép xấp xỉ đối ứng cho căn bậc hai và căn bậc hai.

Hơn nữa, nó vô hiệu hóa số 0 đã ký (mã giả định số 0 đã ký không tồn tại, ngay cả khi mục tiêu hỗ trợ nó) và làm tròn toán học, cho phép trong số những thứ khác liên tục gấp lại trong thời gian biên dịch.

Cuối cùng, nó tạo mã giả định rằng không có sự cố ngắt phần cứng nào có thể xảy ra do toán học báo hiệu / bẫy (nghĩa là, nếu những điều này không thể bị vô hiệu hóa trên kiến ​​trúc đích và do đó sẽ xảy ra , chúng sẽ không được xử lý).


15
Chết tiệt, cảm ơn! Bạn có thể thêm một số tài liệu tham khảo? Giống như gcc.gnu.org/onlinesocs/gcc/Optizes-Options.html " -ffast-math Đặt -fno-math-errno, -funafe-math-tối ưu hóa, -ffinite-math-only, -fno-rounding-math, -fno-signaling -nans và -fcx-Phạm vi giới hạn. Tùy chọn này làm cho macro tiền xử lý FAST_MATH được xác định. "và một cái gì đó từ glibc, như ( math.hgần math_errhandling)" Theo mặc định, tất cả các hàm đều hỗ trợ cả xử lý lỗi và xử lý ngoại lệ. nếu các hàm nội tuyến được xác định thì điều này có thể không đúng. "
osgx

4
@javapowered: Nó có "nguy hiểm" hay không phụ thuộc vào những gì đảm bảo bạn cần. -ffast-mathcho phép trình biên dịch cắt giảm một số góc và phá vỡ một số lời hứa (như đã giải thích), nói chung là không nguy hiểm như vậy và không phải là vấn đề đối với hầu hết mọi người. Đối với hầu hết mọi người, nó giống nhau, chỉ nhanh hơn. Tuy nhiên, nếu mã của bạn giả định và dựa vào những lời hứa này, thì mã của bạn có thể hoạt động khác với mong đợi của bạn. Thông thường, điều này có nghĩa là chương trình dường như sẽ hoạt động tốt, chủ yếu, nhưng một số kết quả có thể là "bất ngờ" (giả sử, trong một mô phỏng vật lý, hai đối tượng có thể không va chạm đúng cách).
Damon

2
@Royi: Hai người nên độc lập với nhau. -O2thường cho phép "mọi" tối ưu hóa hợp pháp, ngoại trừ những quy mô giao dịch với tốc độ. -O3cũng cho phép tối ưu hóa kích thước giao dịch cho tốc độ. Nó vẫn duy trì đúng 100%. -ffast-mathcố gắng làm cho các hoạt động toán học nhanh hơn bằng cách cho phép hành vi "hơi không chính xác" thường không gây hại, nhưng sẽ bị coi là không chính xác theo cách diễn đạt của tiêu chuẩn. Nếu mã của bạn thực sự khác nhau nhiều về tốc độ trên hai trình biên dịch (không chỉ 1-2%) thì hãy kiểm tra xem mã của bạn có tuân thủ các tiêu chuẩn nghiêm ngặt không và ...
Damon

1
... tạo ra các cảnh báo bằng không. Ngoài ra, hãy chắc chắn rằng bạn không gặp rắc rối với các quy tắc răng cưa và những thứ như tự động vector hóa. Về nguyên tắc, GCC nên thực hiện ít nhất là tốt (thường là tốt hơn theo kinh nghiệm của tôi) như MSVC. Khi đó không phải là trường hợp, có lẽ bạn đã mắc một lỗi tinh vi mà MSVC chỉ bỏ qua nhưng điều đó khiến GCC vô hiệu hóa tối ưu hóa. Bạn nên đưa ra cả hai lựa chọn nếu bạn muốn cả hai, vâng.
Damon

1
@Royi: Mã đó trông không thực sự nhỏ và đơn giản đối với tôi, không phải là thứ mà người ta có thể phân tích sâu trong vài phút (hoặc thậm chí vài giờ). Trong số những thứ khác, nó liên quan đến một thứ dường như vô hại #pragma omp parallel for, và trong cơ thể vòng lặp, bạn vừa đọc và viết đến các địa chỉ được chỉ ra bởi các đối số chức năng và thực hiện một số lượng phân nhánh không tầm thường. Như một phỏng đoán không có giáo dục, bạn có thể sẽ phá vỡ bộ nhớ cache từ bên trong các lệnh xử lý được xác định theo triển khai của bạn và MSVC có thể tránh các cửa hàng trung gian mà các quy tắc bí danh sẽ bắt buộc. Không thể nói.
Damon
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.