2009-07-15 18 views
5

Tôi đang tìm xem một lập trình viên có thể làm gì trong C, có thể xác định hiệu suất và/hoặc kích thước của tệp đối tượng được tạo.Thực hành mã hóa C cho hiệu suất hoặc kích thước mã - ngoài những gì mà trình biên dịch thực hiện

Đối với ví dụ,
1. Tuyên bố chức năng get/set đơn giản như inline có thể làm tăng hiệu suất (với chi phí của một dấu chân lớn hơn)
2. Đối với các vòng lặp mà không sử dụng các giá trị của biến vòng lặp chính nó, đếm xuống đến số không thay vì đếm lên đến một giá trị nhất định v.v.

Dường như các trình biên dịch giờ đây đã nâng cao đến mức mà các thủ thuật "đơn giản" (như hai điểm trên) không bắt buộc. Tùy chọn thích hợp trong quá trình biên dịch thực hiện công việc. Heck, tôi cũng thấy các bài viết ở đây về cách trình biên dịch xử lý đệ quy - điều đó rất thú vị! Vậy chúng ta phải làm gì ở cấp độ C? :)

Môi trường cụ thể của tôi là: GCC 4.3.3 nhắm mục tiêu lại cho kiến ​​trúc ARM (v4). Nhưng phản ứng trên các trình biên dịch/bộ vi xử lý khác cũng được chào đón và sẽ được nhai.

PS: Cách tiếp cận này của tôi đi ngược lại với "mã đầu tiên !, sau đó chuẩn, và cuối cùng là tối ưu hóa" phương pháp tiếp cận.

Sửa: Cũng giống như nó xảy ra như vậy, tôi thấy một bài tương tự sau khi đăng câu hỏi: Should we still be optimizing "in the small"?

+0

http://stackoverflow.com/questions/110684/what-coding-techniques-do-you-use-for-optimising-c-programs http://stackoverflow.com/questions/178045/when- nên-bạn-bắt đầu-tối ưu hóa-mã # 178079 http://stackoverflow.com/questions/242149/when-should-i-optimize –

+0

Có gì sai với "mã đầu tiên thông thường !, sau đó là điểm chuẩn và cuối cùng là tối ưu hóa" tiếp cận? –

+0

Không có gì sai với điều đó - nó _should_ là cách tối ưu hóa được thực hiện. Động cơ của tôi là kiểm tra xem tôi có thể thực hiện một công cụ để tái cấu trúc mã (sau khi lược tả được thực hiện) để giúp một nhà phát triển thay đổi nhanh chóng cho hiệu suất và/hoặc khu vực. Hãy tưởng tượng một plugin Eclipse (hoặc một kịch bản vim) làm nổi bật các vòng lặp và cung cấp các tùy chọn để nói, hủy bỏ chúng hoặc để chuyển đổi một vòng lặp bên trong và bên ngoài. Tôi nên làm rõ điều này trong bài viết, xin lỗi về điều đó. Và cảm ơn các liên kết! –

Trả lời

6

Một điều tôi có thể nghĩ rằng một trình biên dịch có thể sẽ không tối ưu hóa là "bộ nhớ cache thân thiện": Nếu bạn đang lặp qua một mảng hai chiều theo thứ tự hàng lớn, hãy chắc chắn rằng vòng lặp bên trong của bạn chạy qua chỉ mục cột để tránh bị tràn bộ nhớ cache. Có vòng lặp bên trong chạy trên chỉ mục sai có thể gây ra một hit hiệu suất rất lớn.

Điều này áp dụng cho tất cả các ngôn ngữ lập trình, nhưng nếu bạn đang lập trình bằng C, hiệu suất có thể rất quan trọng đối với bạn, vì vậy nó có liên quan đặc biệt.

+0

Bộ vi xử lý AFAIK ARM v4 không có bộ nhớ cache. – starblue

+0

Phụ thuộc ... một số thành viên của gia đình, một số thì không. (http://en.wikipedia.org/wiki/ARM_architecture) –

5

"Luôn luôn" biết thời gian và không gian phức tạp của thuật toán của bạn. Trình biên dịch sẽ không bao giờ có thể thực hiện công việc đó cũng như bạn có thể. :)

1

PreComputation nếu có thể ... (xin lỗi nhưng nó không phải luôn luôn có thể ... Tôi đã mở rộng precomputation trên cờ vua của tôi động cơ.) Lưu trữ những kết quả trong bộ nhớ, giữ bộ nhớ cache trong tâm trí .. lớn hơn kích thước của precomputation dữ liệu trong bộ nhớ ít hơn là cơ hội làm một bộ nhớ cache hit. Vì hầu hết phần cứng gần đây là đa lõi, bạn có thể thiết kế ứng dụng của mình để nhắm mục tiêu nó.

nếu bạn đang sử dụng một vài mảng lớn chắc chắn rằng bạn nhóm chúng gần nhau vào nơi họ sẽ được sử dụng, thúc đẩy bộ nhớ cache hit

3

Trình biên dịch những ngày này vẫn không phải là rất tốt tại vectorizing mã của bạn vì vậy bạn' vẫn sẽ muốn thực hiện SIMD của hầu hết các thuật toán.

Chọn đúng cơ sở dữ liệu cho vấn đề chính xác của bạn có thể tăng hiệu suất đáng kể (Tôi đã thấy các trường hợp di chuyển từ cây Kd đến BVH sẽ làm điều đó, trong trường hợp cụ thể đó).

Trình biên dịch có thể đệm một số cấu trúc/biến để vừa với bộ nhớ cache nhưng các tối ưu hóa bộ nhớ cache khác như vị trí dữ liệu của bạn vẫn tùy thuộc vào bạn.

Trình biên dịch vẫn không tự động làm cho mã của bạn được đa luồng và sử dụng openmp, theo kinh nghiệm của tôi, không thực sự hữu ích nhiều.(Bạn thực sự phải hiểu openmp anyway để tăng hiệu suất đáng kể). Vì vậy, hiện tại, bạn đang trên của riêng bạn làm đa luồng.

2

Để thêm vào những gì Martin nói trên về bộ nhớ cache thân thiện:

  • sắp xếp lại cấu trúc của bạn như vậy mà các lĩnh vực mà thường được truy cập với nhau là trong dòng bộ nhớ cache tương tự có thể giúp (ví dụ bằng cách tải chỉ là một bộ nhớ cache dòng chứ không phải là hai.) Về cơ bản bạn đang tăng mật độ dữ liệu hữu ích trong bộ nhớ cache dữ liệu của mình bằng cách thực hiện việc này. Có một công cụ linux có thể giúp bạn làm điều này: người lùn 1. http://www.linuxinsight.com/files/ols2007/melo-reprint.pdf

  • bạn có thể sử dụng một chiến lược tương tự để tăng mật độ mã của bạn. Trong gcc, bạn có thể đánh dấu các nhánh nóng và lạnh bằng cách sử dụng các thẻ khả năng/không chắc chắn. Điều đó cho phép gcc để giữ cho các chi nhánh lạnh một cách riêng biệt giúp tăng mật độ icache.

Và bây giờ cho một cái gì đó hoàn toàn khác nhau:

  • cho các lĩnh vực mà có thể được truy cập (đọc viết) trên CPU, chiến lược đối diện có ý nghĩa. Vấn đề là đối với mục đích kết hợp chỉ có một CPU có thể được phép ghi vào cùng một địa chỉ (trong thực tế cùng một đường dẫn.) Điều này có thể dẫn đến một điều kiện được gọi là ping pong cache-line. Điều này khá tệ và có thể tồi tệ hơn nếu dòng bộ nhớ cache đó chứa dữ liệu không liên quan khác. Ở đây, đệm dữ liệu được tranh luận này vào độ dài dòng bộ nhớ cache có ý nghĩa.

Lưu ý: đây rõ ràng là tối ưu hóa vi mô, chỉ được thực hiện ở các giai đoạn sau khi bạn đang cố gắng vắt các bit hiệu suất cuối cùng từ mã của mình.

0

Nhiều người không nhận thức được điều này: Xác định nhãn nội tuyến (thay đổi theo trình biên dịch) có nghĩa là nội tuyến, trong mục đích của nó - nhiều trình biên dịch đặt từ khóa trong ngữ cảnh hoàn toàn khác với ý nghĩa ban đầu. Ngoài ra còn có những cách để tăng giới hạn kích thước nội tuyến, trước khi trình biên dịch bắt đầu popping những thứ tầm thường ra khỏi dòng. Con người chỉ đạo nội tuyến có thể sản xuất mã nhanh hơn nhiều (trình biên dịch thường là bảo thủ, hoặc không tính đủ cho chương trình), nhưng bạn cần phải học cách sử dụng nó một cách chính xác, vì nó có thể (dễ) phản tác dụng. Và có, điều này hoàn toàn áp dụng cho kích thước mã cũng như tốc độ.

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