2012-02-23 11 views
12

Sau khi đọc xung quanh chủ đề, có nhiều bằng chứng từ nhiều nguồn sử dụng tiêu chuẩn C hoặc C++ phôi để chuyển đổi từ dấu phẩy động sang số nguyên trên Intel rất chậm. Để đáp ứng đặc tả ANSI/ISO, các CPU Intel cần thực hiện một số lượng lớn các lệnh bao gồm cả các lệnh cần thiết để chuyển đổi chế độ làm tròn của phần cứng FPU.Làm cách nào để đảm bảo dấu ấn được gạch chân trong gcc?

Có một số cách giải quyết được mô tả trong các tài liệu khác nhau, nhưng rõ ràng nhất và di động nhất có vẻ là lời gọi() được thêm vào các tiêu chuẩn C99 và C++ 0x. Nhiều tài liệu nói rằng một trình biên dịch nên nội tuyến mở rộng các chức năng này khi tối ưu hóa được kích hoạt, dẫn đến mã đó là nhanh hơn so với một diễn viên thông thường, hoặc một cuộc gọi chức năng.

Tôi thậm chí còn tìm thấy các tham chiếu đến các túi theo dõi tính năng gcc để thêm phần mở rộng nội tuyến này vào trình tối ưu hoá gcc, nhưng trong các thử nghiệm hiệu suất của riêng tôi, tôi không thể làm cho nó hoạt động. Tất cả các nỗ lực của tôi cho thấy hiệu suất in ấn chậm hơn nhiều so với dàn diễn viên C hoặc C++ đơn giản. Kiểm tra đầu ra lắp ráp của trình biên dịch, và tháo các đối tượng đã biên dịch luôn hiển thị một lời gọi rõ ràng đến một hàm bên ngoài() hoặc lrintf() bên ngoài.

Phiên bản gcc tôi đã làm việc với 4.4.3 và 4.6.1 và tôi đã thử một số kết hợp cờ trên các mục tiêu 32bit và 64bit x86, bao gồm các tùy chọn để bật SSE rõ ràng.

Làm cách nào để nhận được gcc để mở rộng nội dòng, và cho tôi chuyển đổi nhanh?

+1

Bạn đã thực sự lược tả và xác nhận rằng sử dụng diễn viên rõ ràng đang dùng một số lượng đáng kể thời gian chạy chương trình của bạn? –

+2

Hồ sơ cho thấy rằng tôi có thể nhận được chênh lệch tốc độ 2-4% bằng cách sử dụng macro được viết bằng tay được nâng lên từ một bài viết. Điều này là đáng giá khi tính toán đang được thực hiện giữa các khung của một ứng dụng dựng hình 3D. –

+1

bạn đã đặt '-fno-math-errno' chưa? bạn cũng nên xem xét sử dụng '-ffast-math', mà không phải lúc nào cũng là một tùy chọn nếu bạn dựa vào các ngữ nghĩa fp cụ thể ... – Christoph

Trả lời

10

Chức năng lrint() có thể làm tăng lỗi miền và phạm vi. Một cách có thể là libc xử lý các lỗi như vậy là thiết lập errno (xem phần C99/C11 7.12.1). Chi phí kiểm tra lỗi có thể khá đáng kể và trong trường hợp cụ thể này dường như là đủ để trình tối ưu hóa quyết định chống lại nội tuyến.

Cờ gcc -fno-math-errno (là một phần của -ffast-math) sẽ vô hiệu hóa các kiểm tra này. Nó có thể là một ý tưởng tốt để xem xét -ffast-math nếu bạn không dựa vào xử lý tuân thủ tiêu chuẩn của ngữ nghĩa dấu phẩy động, cụ thể là NaN và infinities ...

0

Bạn đã thử cờ -finline-functions thành gcc chưa.

Bạn có thể GCC cũng trực tiếp để cố gắng tích hợp tất cả “đơn giản đủ” chức năng vào người gọi họ với các tùy chọn -finline-functions.

thấy http://gcc.gnu.org/onlinedocs/gcc/Inline.html

Ở đây bạn có thể nói gcc để làm cho tất cả các chức năng để nội tuyến nhưng không phải tất cả sẽ được gạch chân. Trình biên dịch sử dụng một số chẩn đoán để xác định xem hàm có đủ nhỏ để được gạch chân không. Một điều nữa là chức năng đệ quy cũng sẽ không có nội tuyến ở đây.

+0

Tôi đã thử -finline-chức năng và nó không có sự khác biệt cho đầu ra trình biên dịch. –

+0

nếu bạn đang sử dụng lrint() của thư viện toán học trong mã của bạn và biên dịch nó bằng gcc thì dấu ấn() sẽ không được gạch chân vì trong trường hợp của bạn, nó sẽ đến từ thư viện liên kết nhị phân. mã của dấu ấn() sẽ không được gạch chân ở đây –

+0

Tài liệu này cho biết cách khác: http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html "Hàm ISO C99 ..... lrintf, lrintl, lrint ...... được xử lý như các chức năng tích hợp ngoại trừ chế độ ISO C90 nghiêm ngặt (-ansi hoặc -std = c90). " Tăng thêm tài liệu mà nó nói: "Nhiều chức năng này chỉ được tối ưu hóa trong một số trường hợp nhất định, nếu chúng không được tối ưu hóa trong một trường hợp cụ thể, một cuộc gọi đến chức năng thư viện sẽ được phát ra." nhưng tôi đã không thể tìm ra một trường hợp mà chúng được tối ưu hóa. –