2010-08-06 29 views
5

Tôi sẽ chia câu hỏi này thành các câu hỏi phụ. Tôi bối rối nếu tôi nên hỏi riêng họ hoặc trong một câu hỏi. Vì vậy, tôi sẽ chỉ dính vào một câu hỏi SO.các bước/chiến lược để phân tích và cải thiện hiệu suất của hệ thống nhúng

  1. Nói chung, các bước để phân tích và cải thiện hiệu suất của ứng dụng C là gì?

  2. Các bước này có thay đổi không nếu tôi đang phát triển cho hệ thống nhúng?

  3. Công cụ nào có thể giúp tôi?

Gần đây, tôi đã được giao nhiệm vụ cải thiện hiệu suất của sản phẩm trên nền tảng ARM11. Tôi tương đối mới với lĩnh vực này của hệ thống nhúng và cần rất kinh nghiệm ở đây trên SO để giúp tôi ra ngoài.

+1

Có hệ điều hành nào không? Nó là gì? Bạn đang sử dụng trình biên dịch/chuỗi công cụ nào? Bạn có GPIO phụ tùng? Bạn có mô phỏng làm việc không? _Embedded_ là một lĩnh vực lớn. – nategoose

Trả lời

4

đơn giản thay đổi trình biên dịch có thể cải thiện hiệu suất C của bạn cho cùng một mã nguồn nhiều lần. GCC đã không nhất thiết phải nhận được tốt hơn cho hiệu suất trong những năm qua, đối với một số chương trình gcc 3.x sản xuất mã chặt chẽ hơn 4.x. Quay lại khi tôi có quyền truy cập vào các công cụ, trình biên dịch ARM tạo ra mã tốt hơn đáng kể so với gcc. Nhanh gấp 3 đến 4 lần. LLVM đã bắt kịp với GCC 4.x và tôi nghi ngờ sẽ vượt qua gcc theo hiệu suất và sử dụng tổng thể cho việc biên dịch chéo mã nhúng. Hãy thử các phiên bản khác nhau của gcc, 3.x và 4.x nếu bạn đang sử dụng gcc. Metaware của trình biên dịch và cánh tay adt chạy vòng tròn xung quanh gcc3.x, gcc3.x sẽ cung cấp cho gcc4.xa chạy cho tiền của mình với mã cánh tay, cho mã ngón tay cái gcc4.x là tốt hơn và cho thumb2 (mà doesnt áp dụng cho bạn) gcc4.x cũng tốt hơn. Hãy nhớ rằng tôi đã không nói một từ về việc thay đổi một dòng mã (chưa).

LLVM có khả năng tối ưu hóa toàn bộ chương trình ngoài các núm điều chỉnh vô hạn hơn gcc. Mặc dù mã được tạo ra (ver 27) chỉ là bắt kịp với gcc 4.x hiện tại về hiệu suất cho một vài chương trình mà tôi đã thử.Và tôi đã không thử kết hợp tối ưu hóa thực tế (tối ưu hóa bước biên dịch, các tùy chọn khác nhau cho mỗi tệp hoặc kết hợp hai tệp hoặc ba tệp hoặc tất cả các tệp và tối ưu hóa các gói đó, lý thuyết của tôi không tối ưu hóa từ C đến bc bước, liên kết tất cả các bc với nhau sau đó làm một tối ưu hóa duy nhất vượt qua trên toàn bộ chương trình, cho phép tối ưu hóa mặc định khi llc đưa nó đến mục tiêu).

Bằng cùng một mã thông báo, chỉ cần biết trình biên dịch của bạn và tối ưu hóa có thể cải thiện đáng kể hiệu suất của mã mà không phải thay đổi bất kỳ mã nào. Bạn có một ARM11 arr bạn biên dịch cho arm11 hoặc chung cánh tay? Bạn có thể đạt được một vài đến một chục phần trăm bằng cách nói cho trình biên dịch cụ thể mà kiến ​​trúc/gia đình (armv6 ví dụ) trên armv4 chung (ARM7) thường được chọn làm mặc định. Biết sử dụng -O2 hoặc -O3 nếu bạn dũng cảm.

Nó thường không phải là trường hợp, nhưng chuyển sang chế độ ngón tay cái có thể cải thiện hiệu suất cho nền tảng cụ thể. Không áp dụng cho bạn, nhưng sự thăng tiến của game thủ là một ví dụ hoàn hảo, được tải với các trạng thái chờ 16 bit khác. Ngón tay cái có một số tiền trên chi phí phần trăm vì cần nhiều hướng dẫn hơn để làm điều tương tự, nhưng bằng cách tăng thời gian tìm nạp và tận dụng một số tính năng đọc tuần tự của mã ngón tay cái có thể chạy nhanh hơn đáng kể so với mã cánh tay cho cùng một mã nguồn.

có arm11 bạn có thể có L1 và bộ nhớ cache L2 có thể đang bật? Chúng có được cấu hình không? Bạn có một mmu và bộ nhớ sử dụng nặng của bạn được lưu trữ? hoặc là bạn đang chạy không chờ đợi bộ nhớ nhà nước và không cần một bộ nhớ cache và nên tắt nó đi? Ngoài việc không nhận ra rằng bạn có thể lấy cùng mã nguồn và làm cho nó chạy nhanh hơn nhiều lần bằng cách thay đổi các trình biên dịch hoặc tùy chọn, mọi người thường không nhận ra rằng khi bạn sử dụng bộ nhớ đệm, chỉ cần thêm một lần lên một vài bước trong mã khởi động của bạn (như là một mẹo để điều chỉnh nơi mã đất trong bộ nhớ bằng một, hai, một vài từ) bạn có thể thay đổi tốc độ thực thi mã của bạn bằng 10 đến 20 phần trăm. Nơi mà các dòng bộ nhớ cache đọc hit trong các chức năng được sử dụng rất nhiều/vòng làm cho một sự khác biệt lớn. Thậm chí tiết kiệm một dòng bộ nhớ cache đọc bằng cách điều chỉnh nơi mã đất là đáng chú ý (cắt nó từ 3 đến 2 hoặc 2-1 ví dụ).

Biết kiến ​​trúc của bạn, cả bộ xử lý và môi trường bộ nhớ của bạn là nơi điều chỉnh nếu có bất kỳ khởi động nào. Hầu hết các thư viện C nếu bạn đủ cao để sử dụng một thư viện (tôi thường không sử dụng thư viện C khi chạy mà không có hệ điều hành và tài nguyên rất hạn chế) cả trong mã C và đôi khi thêm một số trình biên dịch để thực hiện các thủ tục tắc nghẽn như memcpy, nhanh hơn nhiều. Nếu các chương trình của bạn hoạt động trên 32 hoặc thậm chí tốt hơn địa chỉ 64 bit, và bạn điều chỉnh ngay cả khi nó có nghĩa là sử dụng một số byte nhiều bộ nhớ hơn cho mỗi cấu trúc/mảng/memcpy thành một bội số của 32 bit hoặc 64 bit bạn sẽ thấy cải tiến đáng chú ý (nếu mã của bạn sử dụng cấu trúc hoặc sao chép dữ liệu theo những cách khác). Ngoài việc nhận được cấu trúc của bạn (nếu bạn sử dụng chúng, tôi chắc chắn không có mã nhúng), ngay cả khi bạn lãng phí bộ nhớ, nhận các phần tử được căn chỉnh, hãy cân nhắc sử dụng các số nguyên 32 bit cho mỗi phần tử thay vì byte hoặc halfwords. Tùy thuộc vào hệ thống bộ nhớ của bạn điều này có thể giúp (nó có thể làm tổn thương quá btw). Như với ví dụ GBA ở trên nhìn vào các hàm cụ thể mà bằng cách lược tả hoặc trực giác, bạn biết không được triển khai theo cách tận dụng bộ xử lý hoặc nền tảng hoặc thư viện bạn có thể muốn chuyển sang trình biên dịch hoặc từ đầu hoặc biên dịch từ C ban đầu sau đó tháo và điều chỉnh tay. Memcpy là một ví dụ tốt, bạn có thể biết hiệu năng bộ nhớ hệ thống của bạn và có thể chọn để tạo riêng memcpy của bạn đặc biệt cho dữ liệu liên kết, sao chép 64 hoặc 128 hoặc nhiều bit cho mỗi hướng dẫn.

Tương tự, trộn các biến toàn cầu và cục bộ có thể tạo ra sự khác biệt hiệu suất đáng chú ý. Theo truyền thống, người ta không bao giờ sử dụng globals, nhưng trong nhúng này không nhất thiết phải đúng, phụ thuộc vào mức độ nhúng sâu và bao nhiêu điều chỉnh và tốc độ và các yếu tố khác mà bạn quan tâm. Đây là một chủ đề nhạy cảm và tôi có thể bị quấy rầy vì nó, Tôi sẽ để nó ở đó.

Trình biên dịch phải ghi và xóa sổ đăng ký để thực hiện cuộc gọi hàm, cộng với nếu bạn sử dụng biến cục bộ, có thể cần có khung ngăn xếp, vì vậy cuộc gọi hàm rất tốn kém, nhưng đồng thời, tùy thuộc vào mã trong chức năng hiện đã tăng kích thước bằng cách tránh các hàm, bạn có thể tạo ra sự cố mà bạn đang cố gắng tránh, xóa sổ đăng ký để sử dụng lại chúng. Ngay cả một dòng mã C có thể tạo sự khác biệt giữa tất cả các biến trong một hàm phù hợp trong sổ đăng ký để bắt đầu gỡ bỏ một loạt các thanh ghi. Đối với các chức năng hoặc phân đoạn của mã mà bạn biết bạn cần một số biên dịch hiệu suất được biên dịch và tháo rời (và xem xét việc sử dụng đăng ký, tần suất nó tải bộ nhớ hoặc ghi vào bộ nhớ). Bạn có thể và sẽ tìm thấy những nơi mà bạn cần phải sử dụng một vòng lặp được sử dụng tốt và làm cho nó trở thành chức năng riêng của nó mặc dù lời gọi hàm có một hình phạt bởi vì làm như vậy trình biên dịch có thể tối ưu hóa tốt hơn vòng lặp và không gỡ bỏ/đăng ký lại. tổng lợi nhuận ròng. Ngay cả một hướng dẫn thêm trong một vòng lặp mà đi xung quanh hàng trăm lần là một hit hiệu suất đo lường.

Hy vọng rằng bạn đã biết hoàn toàn không biên dịch để gỡ lỗi, hãy tắt tất cả các biên dịch cho các tùy chọn gỡ lỗi. Bạn có thể đã biết rằng mã biên dịch để gỡ lỗi chạy mà không có lỗi không có nghĩa là nó được sửa lỗi, biên dịch để gỡ rối và sử dụng các trình gỡ rối ẩn các lỗi để chúng như các quả bom thời gian trong mã của bạn để biên dịch cuối cùng của bạn để phát hành. Tìm hiểu để luôn luôn biên dịch cho phát hành và thử nghiệm với phiên bản phát hành cho cả hiệu suất và tìm lỗi trong mã của bạn.

Hầu hết các bộ lệnh không có chức năng phân chia. Tránh sử dụng phân chia hoặc modulo trong mã của bạn càng nhiều càng tốt, chúng có thể là những kẻ giết người thực hiện. Đương nhiên đây không phải là trường hợp cho quyền hạn của hai, để lưu trình biên dịch và tinh thần tránh chia và modulos cố gắng sử dụng ca và ands. Multplies dễ dàng hơn và thường được tìm thấy trong các tập lệnh, nhưng vẫn tốn kém. Đây là một trường hợp tốt để viết assembler để làm nhân của bạn thay vì để cho C copiler làm điều đó. Các cánh tay nhân là 32bit * 32bit = 32 bit để làm toán chính xác mà không tràn phải có thêm mã C bọc xung quanh nhân, nếu bạn đã biết bạn sẽ không tràn, ghi các đăng ký cho một cuộc gọi chức năng và làm nhân trong lắp ráp (cho cánh tay).

Tương tự như vậy, hầu hết các bộ lệnh không có một đơn vị dấu chấm động, với bạn có thể, ngay cả như vậy tránh nổi nếu có thể. Nếu bạn phải sử dụng float, đó là một hộp toàn bộ các vấn đề hiệu suất của pandora khác. Hầu hết mọi người không nhìn thấy các vấn đề hiệu suất với mã đơn giản như này:

 

float a,b; 

... 

a = b * 7.0; 

Phần còn lại của vấn đề là không hiểu nổi chính xác điểm và làm thế nào tốt hay xấu các thư viện C chỉ là cố gắng để có được hằng số của bạn thành điểm nổi hình thức. Một lần nữa float là một cuộc thảo luận dài khác về các vấn đề hiệu năng.

Tôi là sản phẩm của Michael Abrash (Tôi thực sự có bản sao zen của ngôn ngữ lắp ráp) và dòng dưới cùng là thời gian mã của bạn. Hãy tìm ra một cách chính xác để mã hóa thời gian, bạn có thể nghĩ rằng bạn biết các nút cổ chai ở đâu và bạn có thể nghĩ rằng bạn biết kiến ​​trúc của mình, nhưng hãy thử những thứ khác nhau ngay cả khi bạn nghĩ chúng sai, và định thời gian cho chúng. tìm ra lỗi trong suy nghĩ của bạn. Khi bước điều chỉnh cuối cùng là một ví dụ tốt về điều này, tất cả công việc khác bạn đã thực hiện cho hiệu năng có thể bị xóa ngay lập tức bởi không có sự liên kết tốt với bộ đệm, điều này cũng có nghĩa là sắp xếp lại các chức năng trong mã nguồn để chúng hạ cánh ở các vị trí khác nhau trong hình ảnh nhị phân. Tôi đã thấy 10 đến 20 phần trăm thay đổi tốc độ tăng và giảm như là kết quả của sự sắp xếp đường bộ nhớ cache.

-1
  1. Bạn phải sử dụng hồ sơ. Nó sẽ giúp bạn xác định các nút cổ chai của ứng dụng của bạn. Sau đó, tập trung vào việc cải thiện các chức năng bạn dành nhiều thời gian nhất và những chức năng bạn gọi nhiều nhất. Lặp lại quy trình này cho đến khi bạn hài lòng với hiệu suất ứng dụng của mình.

  2. Không, không.

  3. Tùy thuộc vào nền tảng này bạn đang phát triển lên:

    Windows: AMD Mã Chuyên viên phân tích, VTune, Sleepy

    Linux: valgrind/callgrind/cachegrind

    Mac: các hồ sơ Xcode là khá tốt.

Cố gắng tìm một hồ sơ cho kiến ​​trúc bạn thực sự làm việc.

+0

2 - họ có thể phần nào nếu bạn đang nhắm mục tiêu cái gì đó không phải là Windows, Linux, Mac hoặc hệ điều hành lớp máy tính để bàn khác.Chúng thay đổi nhiều hơn khi bạn không thể chạy mã của bạn trên máy tính để bàn của bạn và thậm chí nhiều hơn khi bạn không có cổng nối tiếp, gpio thêm, hoặc ICE phong nha. – nategoose

+0

Câu trả lời của bạn là Pc cụ thể nên câu hỏi 2. là có. – Gerhard

1
  1. Mã Đánh giá:

    What are good code review techniques ?

    phân tích tĩnh và năng động của mã này.

    Công cụ để phân tích tĩnh: Sparrow, Ngăn chặn, Klockworks

    Công cụ để phân tích năng động: Valgrind, purify

    Gprof cho phép bạn để tìm hiểu nơi chương trình của bạn dành thời gian của mình và có chức năng gọi mà các chức năng khác trong khi nó đang thực hiện.

  2. bước là cùng

  3. Ngoài những gì được liệt kê là điểm 1, có các công cụ như memcheck, vv Có một danh sách lớn here dựa trên nền tảng

0

Đó là một câu hỏi khó có thể trả lời trong thời gian ngắn kể từ khi kỹ thuật khác nhau đã được đề xuất như sơ đồ và sơ đồ nhà nước, vì vậy bạn có thể có một cái nhìn tại một số danh hiệu:

ARM System-on-Chip Kiến trúc, 2nd Edition - Steve Furber

ARM Hệ thống phát triển của Hướng dẫn - Phần mềm Thiết kế và tối ưu hóa hệ thống - Andrew N. Sloss, Dominic Symes, Chris Wright & John Rayfield

The Definitive Guide vào thư mục C Lập trình ARM Cortex-M3 --Joseph Yiu

cho Embedded Systems --Kirk Zurell

Embedded C - Michael J. Pont

Lập trình Hệ thống nhúng trong C và C++ --Michael Barr

Một phần mềm nhúng Primer --David E, Simon

Embedded Systems vi xử lý 3rd Edition --Stuart bóng

Đặc điểm chung và xác thực hệ thống nhúng - Tích hợp các thành phần không đồng nhất --G. Nicolescu & AA Jerraya

Hệ thống nhúng: Modeling, Công nghệ và ứng dụng --Gunter Hommel & Sheng Huanye

Embedded Systems và Kiến trúc máy tính --Graham Wilson

Thiết kế Embedded Hardware --John Catsoulis

1

Phew !! Một câu hỏi lớn!

Nói chung, các bước để phân tích và cải thiện hiệu suất của ứng dụng C là gì?

Cũng như các trình phân tích mã tĩnh khác được đề cập ở đây có phiên bản khá rẻ gọi là PC-Lint đã có tuổi. Đôi khi ném rất nhiều lỗi và cảnh báo cho một lỗi nhưng vào cuối của nó, bạn sẽ được hạnh phúc và biết waaaaay thêm về C/C++ vì nó.

Với tất cả các trình phân tích mã, một số vấn đề có thể có cấu trúc nhiều hơn với mã tốt nhất để bắt đầu phân tích nó từ ngày 1 của mã hóa; chạy phân tích trên phần mềm cũ có thể làm bạn khó khăn với các vấn đề có thể mất một lúc để gỡ rối, tốt nhất là giữ cho nó sạch sẽ ngay từ đầu.

Nhưng các trình phân tích mã sẽ không bắt được tất cả các lỗi logic, tức là nó không làm những gì bạn muốn nó làm! Điều này được thực hiện tốt nhất bằng cách đánh giá mã đầu tiên, sau đó kiểm tra. Hiệu suất thường được cải thiện bằng cách cố gắng giữ các thuật toán đơn giản nhất có thể, giữ hướng dẫn trong các vòng lặp chặt chẽ, có thể bỏ vòng lặp (tối ưu hóa trình biên dịch của bạn có thể làm điều này), sử dụng cache nhanh khi truy cập dữ liệu chậm.

Đánh giá mã có thể gây ra nhiều vấn đề từ rất nhiều người khác nhìn vào nó.Đừng có quá nhiều người, cố gắng kiếm 3 người khác nếu có thể, đôi khi các nhà phát triển cơ sở hỏi những câu hỏi sâu sắc nhất như, "tại sao chúng ta lại làm điều này?".

Thử nghiệm có thể được chia thành hai phần, tự động và thủ công. Thử nghiệm tự động đòi hỏi nỗ lực sản xuất trình xử lý kiểm tra cho các chức năng/đơn vị nhưng một khi chạy có thể chạy lại rất nhanh. Kiểm tra thủ công đòi hỏi phải lập kế hoạch, tự kỷ luật để thực hiện tất cả các yêu cầu, trí tưởng tượng để suy nghĩ về các kịch bản có thể làm giảm hiệu suất và bạn phải quan sát (có thể bạn đã vượt qua bài kiểm tra nhưng 'phạm vi theo dõi có một chút bất thường trước/sau khi thử nghiệm).

"Các bước này có thay đổi nếu tôi đang phát triển cho hệ thống nhúng không?"

Hiệu suất ananlysis có thể khác nhau trên hệ thống nhúng vào hệ thống ứng dụng; với bàn chải rất rộng mà "nhúng" bây giờ bao gồm nó phụ thuộc vào phần cứng trung tâm bạn đang có. Nó có thể được thực hiện bằng cách sử dụng profilers, nếu bạn muốn một phương pháp rẻ hơn và chearful sau đó sử dụng các chân đầu ra thử nghiệm để đo các phần mã, hoặc đo chúng với các điểm ngắt trên mô phỏng đi kèm với môi trường phát triển.

Đảm bảo rằng không chỉ là một nhiệm vụ điển hình được đo mà còn là tối đa, vì đó là nơi một nhiệm vụ có thể bắt đầu cản trở các nhiệm vụ khác và nhiệm vụ theo lịch của bạn không hoàn thành kịp thời.

Những công cụ nào ở ngoài có thể giúp tôi?

mô phỏng trên IDE, các công cụ phân tích tĩnh, công cụ phân tích năng động, nhưng hầu hết tất cả các bạn và người khác nhận được yêu cầu phải, rà soát phong nha (mã và thử nghiệm) và thử nghiệm kỹ lưỡng (tự động và thủ).

Chúc may mắn!

1

Trải nghiệm của tôi.

  1. Cuộc gọi chức năng chậm, loại bỏ bằng macro hoặc phương pháp được gạch chân. Nhìn vào danh sách disassembler để xem.
  2. Nếu sử dụng GCC, hãy đánh dấu các phần được tối ưu hóa bằng #pragma GCC optimize("O3") hoặc biên dịch chúng một cách riêng biệt.
  3. Chơi với các kết hợp khác nhau của việc áp dụng thuộc tính nội tuyến (về cơ bản tìm thấy sự cân bằng giữa kích thước và tốc độ).
Các vấn đề liên quan