8

Tôi đang viết phần mềm số thời gian thực, trong C++, hiện đang biên dịch nó bằng Visual-C++ 2008. Bây giờ sử dụng mô hình điểm nổi 'nhanh' (/fp:fast), các tối ưu hóa khác nhau , hầu hết chúng hữu ích cho trường hợp của tôi, nhưng cụ thể là:Tùy chọn trình biên dịch C++ điểm nổi | ngăn chặn a/b -> a * (1/b)

a/b -> a*(1/b) Division by multiplicative inverse 

quá số không ổn định cho nhiều tính toán của tôi.

(xem: Microsoft Visual C++ Floating-Point Optimization)

Chuyển sang /fp:precise làm cho ứng dụng của tôi chạy hơn gấp đôi chậm. Có thể tinh chỉnh trình tối ưu hóa (ví dụ: vô hiệu hóa tối ưu hóa cụ thể này) hay bằng cách nào đó bỏ qua nó bằng tay không?

- thực tế tối thiểu-mã ví dụ: -

[thuật toán mã thực tế của tôi là chủ yếu là ma trận liên quan]
void test(float a, float b, float c, 
    float &ret0, float &ret1) { 
    ret0 = b/a; 
    ret1 = c/a; 
} 

Output: VC (cl, phiên bản 15, 0x86) là:

divss  xmm0,xmm1 
mulss  xmm2,xmm0 
mulss  xmm1,xmm0 

Có một div, thay vì hai là một vấn đề lớn về số lượng, (xmm0, được tải trước với 1.0f từ RAM), tùy thuộc vào giá trị của xmm1,2 (có thể khác với r anges) bạn có thể mất rất nhiều độ chính xác (Biên dịch không có SSE, xuất ra mã stack-x87-FPU tương tự).

Bao bì các chức năng với

#pragma float_control(precise, on, push) 
... 
#pragma float_control(pop) 

Có giải quyết vấn đề chính xác, nhưng trước hết, nó chỉ có sẵn trên một hàm cấp (toàn cầu phạm vi), và thứ hai, nó ngăn chặn nội tuyến của hàm, (tức , hình phạt tốc độ quá cao)

đầu ra 'chính xác' đang được đúc để 'đúp' qua lại như giếng:

divsd  xmm1,xmm2 
cvtsd2ss xmm1,xmm1 
divsd  xmm1,xmm0 
cvtpd2ps xmm0,xmm1 
+2

Bất kỳ phép toán điểm động nào dựa trên sự bình đẳng sẽ không ổn định. –

+1

@Hans: OP không tìm kiếm sự bình đẳng; anh/cô ấy nói rằng trình biên dịch đang thực hiện việc thay thế ở trên làm tối ưu hóa và điều này là vô ích trong ứng dụng của anh ấy/cô ấy. –

+0

@Oli: vẫn còn, chúng tôi không biết liệu các yêu cầu về độ chính xác của OP có đạt được hay không. – peterchen

Trả lời

0

(Weird) giải pháp mà tôi đã tìm thấy: bất cứ khi nào chia cho cùng một giá trị trong một chức năng - thêm một số epsilon:

a/b; c/b 

->

a/(b+esp1); c/(b+esp2) 

Cũng giúp bạn tiết kiệm từ div thỉnh thoảng bởi số không

2

đó bang tài liệu mà bạn có thể kiểm soát tối ưu hóa chỉ trỏ trên cơ sở từng dòng bằng cách sử dụng pragmas.

0

Bạn có thể đặt các hàm có chứa các tính toán đó trong một tệp mã nguồn riêng biệt và chỉ biên dịch tệp đó với các cài đặt khác nhau không?

Tôi không biết điều đó có an toàn hay không, bạn cần kiểm tra!

3

Thêm

#pragma float_control(precise, on)

trước khi tính toán và

#pragma float_control(precise,off)

sau đó. Tôi nghĩ rằng nên làm điều đó.

+0

có, đó là những gì tôi đang sử dụng: #pragma float_control (chính xác, trên, push) ... #pragma float_control (pop) không may, nó dường như chỉ làm việc trên một cấp độ hoàn toàn chức năng, cộng với ngăn chặn nội tuyến. Tôi sẽ thêm một bình luận với những phát hiện hiện tại của tôi. Nó sẽ thực sự rock, nếu có một tùy chọn float-optimization tinh chỉnh hơn – oyd11

1

Ngoài ra còn có __assume. Bạn có thể sử dụng __assume (a/b! = (A * (1/b))). Tôi chưa bao giờ thực sự sử dụng __assume, nhưng về lý thuyết nó tồn tại chính xác để tinh chỉnh trình tối ưu hóa.

+0

Tốt để biết về __assume(), các trình biên dịch khác mà tôi đã sử dụng trước đây có các tùy chọn tương tự (NASSERT trong các trình biên dịch TI). , Tôi nghĩ rằng trình biên dịch đã giả định (a/b! = (A * (1/b))) – oyd11

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