2012-10-16 37 views
5

Tôi biết các lỗi có thể xảy ra khi thực hiện chuyển đổi giữa các số dấu phẩy động và số nguyên, nhưng về hiệu suất (vui lòng bỏ qua các vấn đề về độ chính xác)?chuyển đổi điểm nổi và hiệu suất

Liệu hiệu suất, nói chung, bị ảnh hưởng nếu tôi làm các hoạt động n-ary vào toán hạng của các loại số học khác nhau, có nghĩa là, trên khác nhau các loại dấu chấm động (ví dụ floatdouble) và nổi kết hợp kiểu điểm/số nguyên (ví dụ floatint)? Có tồn tại các quy tắc của ngón tay cái, chẳng hạn như, để giữ cho tất cả các toán hạng cùng loại?

P .: Tôi hỏi vì tôi đang viết một thư viện mẫu biểu thức và muốn biết có cho phép các phép toán nhị phân trên các vectơ chứa các giá trị của các loại số học khác nhau hay không.

+1

Có, có chi phí để chuyển đổi giữa các loại khác nhau. Tôi có thể đưa ra một câu trả lời chuyên sâu nếu không ai khác làm vào lúc tôi trở về từ giữa kỳ. – Mysticial

+0

Vì các phép toán dấu phẩy động không quan trọng về số học cơ sở-2, các trình biên dịch thường phát ra các hàm trợ giúp (xem tại sao libgcc là cần thiết?) Và có thể ảnh hưởng nghiêm trọng đến hiệu suất. –

+0

Vấn đề là, chương trình của bạn không ** thực hiện các thao tác n-ary trên các toán hạng của các kiểu khác nhau. Nó thúc đẩy các đối số theo ví dụ: C99 6.3.1.8 Chuyển đổi số học thông thường, và sau đó hoạt động n-ary diễn ra, thường với các đối số cùng loại (có một vài ngoại lệ nhưng không có ngoại lệ nào liên quan đến các loại dấu phẩy động). –

Trả lời

5

Tôi nghi ngờ câu trả lời cho câu hỏi này sẽ thay đổi theo kiến ​​trúc đích, bởi vì các chuyển đổi có thể (nhưng có thể không) xảy ra trong phần cứng. Ví dụ, hãy xem xét đoạn mã sau, gây ra một số interconversions giữa int và float:

int main (int argc, char** argv) 
{ 
    int precoarced = 35; 
    // precoarced gets forced to float 
    float result = 0.5 + precoarced; 

    // and now we force it back to int 
    return (int)result; 

    // I wonder what the disassembly looks like in different environments? 
} 

Khi tôi cố gắng biên dịch này với g ++ (Tôi đang trên Ubuntu, x86) với các thiết lập mặc định, và sử dụng gdb để tháo rời :

0x00000000004004b4 <+0>: push %rbp 
    0x00000000004004b5 <+1>: mov %rsp,%rbp 
    0x00000000004004b8 <+4>: mov %edi,-0x14(%rbp) 
    0x00000000004004bb <+7>: mov %rsi,-0x20(%rbp) 
    0x00000000004004bf <+11>: movl $0x23,-0x8(%rbp) 
    0x00000000004004c6 <+18>: cvtsi2sdl -0x8(%rbp),%xmm0 
    0x00000000004004cb <+23>: movsd 0x10d(%rip),%xmm1  # 0x4005e0 
    0x00000000004004d3 <+31>: addsd %xmm1,%xmm0 
    0x00000000004004d7 <+35>: unpcklpd %xmm0,%xmm0 
    0x00000000004004db <+39>: cvtpd2ps %xmm0,%xmm0 
    0x00000000004004df <+43>: movss %xmm0,-0x4(%rbp) 
    0x00000000004004e4 <+48>: movss -0x4(%rbp),%xmm0 
    0x00000000004004e9 <+53>: cvttss2si %xmm0,%eax 
    0x00000000004004ed <+57>: pop %rbp 
    0x00000000004004ee <+58>: retq 

Lưu ý các hướng dẫn với tiền tố có tiền tố cvt. Đây là các hướng dẫn chuyển đổi. Vì vậy, trong trường hợp này, quá trình chuyển đổi diễn ra trong phần cứng chỉ trong một số hướng dẫn. Vì vậy, tùy thuộc vào bao nhiêu chu kỳ các hướng dẫn chi phí, nó có thể được hợp lý nhanh chóng. Nhưng một lần nữa, một kiến ​​trúc khác (hoặc trình biên dịch khác) có thể thay đổi câu chuyện.

Chỉnh sửa: Trên một lưu ý thú vị, có thêm một chuyển đổi trong đó do tôi vô tình chỉ định 0,5 thay vì 0,5f. Đó là lý do tại sao cvtpd2ps op nằm trong đó.

Chỉnh sửa: x86 đã có hỗ trợ FP trong một thời gian dài (từ thập niên 80), vì vậy trình biên dịch C++ nhắm mục tiêu x86 thường sẽ sử dụng phần cứng (trừ khi trình biên dịch nghiêm túc sau thời gian). Cảm ơn Hot Licks vì đã chỉ ra điều này.

+0

trình biên dịch có thể đã đủ thông minh để thực hiện chuyển đổi tại thời gian biên dịch, nhưng không phải là ... – user1095108

+0

@ user1095108 Thật vậy. Điều này không làm tôi ngạc nhiên quá nhiều; Tôi đã ở cài đặt mặc định, cho một. Có nổi như một chữ như vậy không phải là một trường hợp sử dụng 'thực tế' điển hình. Ngoài ra, người triển khai trình biên dịch có thể sợ bất kỳ sự tối ưu hóa liên quan đến float nào vì chúng phải * rất cẩn thận. Ví dụ, bạn có thể nghĩ rằng tính tương đối của phép cộng (A + B = B + A) sẽ là cơ sở hợp lệ cho các tối ưu hóa bổ sung float, nhưng do sự thiếu chính xác fp nó không phải là; nó có thể phá vỡ độ chính xác của một số thuật toán FP. – WeirdlyCheezy

+0

Lưu ý rằng hướng dẫn chuyển đổi đã ở đó, dưới dạng này hay dạng khác, kể từ bộ xử lý gốc 8087 ban đầu. Vì vậy, hầu như tất cả các hệ thống với phần cứng dấu chấm động sẽ có các chuyển đổi trong phần cứng. –

2

Trên hầu hết các máy, chuyển đổi giữa các định dạng float và int khá nhanh, được hỗ trợ bởi các tính năng của phần cứng dấu phẩy động.

Tuy nhiên, tất nhiên, nên cố gắng diễn đạt các chữ trong định dạng "chính xác", nếu chỉ cho mục đích tài liệu. Và nó cũng không gây tổn thương khi sử dụng các phôi rõ ràng, cho tài liệu.

2

Thông thường có một số hình phạt về hiệu suất, mặc dù không đáng kể so với những thứ khác. Điều này là do di chuyển dữ liệu giữa các thanh ghi tích phân và dấu phẩy động và các vấn đề ABI khác có thể xảy ra.

Câu trả lời cho những câu hỏi như vậy là luôn luôn giống nhau. Nghi ngờ? Đo điểm chuẩn. Hiệu suất hầu như không thể dự đoán được về mặt lý thuyết.

+2

đừng quên, tôi đã hỏi về quy tắc của ngón cái. Tôi biết quy tắc băng ghế dự bị. – user1095108

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