2012-05-29 27 views
16

Tôi đã phát triển mã C++ để tăng cường thực tế trên thiết bị ARM và tối ưu hóa mã là rất quan trọng để duy trì tốc độ khung hình tốt. Để tăng hiệu quả lên mức tối đa, tôi nghĩ rằng việc thu thập các mẹo chung là làm cho cuộc sống dễ dàng hơn đối với các trình biên dịch và giảm số lượng các phần tử của chương trình. Bất kỳ đề nghị được hoan nghênh.C++ Lời khuyên tối ưu hóa mã trên thiết bị ARM

1- Tránh hướng dẫn chi phí cao: chia, căn bậc hai, sin, cos

  • Sử dụng những thay đổi hợp lý để chia hoặc nhân với 2.
  • Multiply bằng nghịch đảo khi có thể.

2- Tối ưu hóa bên trong "cho" vòng: họ là một botleneck vì vậy chúng tôi nên tránh đưa ra nhiều tính toán bên trong, đặc biệt là các đơn vị, rễ vuông ..

3 Sử dụng nhìn lên bảng đối với một số chức năng toán học (sin, cos, ...)

ÍCH CÔNG cỤ

  • objdump: lấy mã assembly của chương trình biên dịch. Điều này cho phép so sánh hai hàm và kiểm tra xem nó có thực sự được tối ưu hóa hay không.
+8

** Cẩn thận **: ngày nay nút cổ chai là bộ nhớ thường xuyên hơn không (và do đó LUT không tuyệt vời như vậy ...). Nó có thể khác nhau trên ARM, phải thừa nhận, nhưng ... kiểm tra tốt hơn rằng đầu tư cho không có gì. –

+0

Đúng. Nhưng trong các ứng dụng thời gian thực, thực hiện rất nhiều tính toán cho mỗi khung hình, hãy tin tôi rằng tối ưu hóa có thể tiết kiệm "một số khung hình mỗi giây". Nói "một số" là 8fps, như với trường hợp của tôi, đó là lý do tại sao tôi nghĩ câu hỏi này là quan trọng. –

+3

Bạn có khả năng kiểm tra các số liệu khác nhau, như nhớ cache, truy cập bus bộ nhớ, v.v ... không? Điều này cũng rất hữu ích để biết nếu xe buýt mem của bạn là một nút cổ chai. BTW, off-topic, (donostia == San Sebastian)? Nếu vậy, tôi thực sự thích thành phố đó! – Brady

Trả lời

17

Để trả lời câu hỏi của bạn về quy tắc chung khi tối ưu hóa mã C++ cho ARM, sau đây là một vài gợi ý:

1) Như bạn nói , không có hướng dẫn phân chia. Sử dụng thay đổi hợp lý hoặc nhân với nghịch đảo khi có thể.
2) Bộ nhớ chậm hơn nhiều so với thực thi CPU; sử dụng các phép toán logic để tránh các bảng tra cứu nhỏ.
3) Cố gắng viết 32 bit cùng một lúc để tận dụng tốt nhất bộ đệm ghi. Viết quần short hoặc ký tự sẽ làm chậm mã xuống đáng kể. Nói cách khác, nó nhanh hơn để hợp lý-OR các bit nhỏ hơn với nhau và viết chúng như là DWORDS.
4) Hãy nhận biết kích thước bộ nhớ cache L1/L2 của bạn. Như một quy luật chung, chip ARM có bộ nhớ cache nhỏ hơn nhiều so với Intel.
5) Sử dụng SIMD (NEON) khi có thể.Hướng dẫn NEON khá mạnh và cho mã "có thể biến đổi", có thể khá nhanh. NEON nội tại có sẵn trong hầu hết các môi trường C++ và có thể gần như nhanh như viết mã ASM được điều chỉnh bằng tay.
6) Sử dụng gợi ý tìm nạp trước bộ nhớ cache (PLD) để tăng tốc độ đọc vòng lặp. ARM không có logic ưu tiên thông minh theo cách mà các chip Intel hiện đại làm.
7) Không tin tưởng trình biên dịch tạo mã tốt. Nhìn vào đầu ra ASM và viết lại các điểm nóng trong ASM. Đối với thao tác bit/byte, ngôn ngữ C không thể chỉ định mọi thứ hiệu quả như chúng có thể được thực hiện trong ASM. ARM có các lệnh 3-operand mạnh mẽ, các thay đổi đa tải/lưu trữ và "tự do" có thể hoạt động tốt hơn những gì mà trình biên dịch có khả năng tạo ra.

+0

Tôi thích nhân với các thay đổi nghịch đảo và logic. Tôi cũng cố gắng sử dụng điểm cố định trên các thiết bị không có NEON. Tôi sẽ cập nhật bài đăng với các mẹo của bạn, cảm ơn! –

+0

Về 5): Tôi đã thấy khá một vài cuộc thảo luận SO về việc sử dụng nội tại NEON. Tóm lại, có vẻ như rất nhiều người nhận thấy rằng trình biên dịch không tạo ra một công việc rất tốt để dịch nội tại thành mã lắp ráp tốt. Sự đồng thuận dường như là nếu bạn muốn sử dụng NEON, bạn nên viết nó như là mã lắp ráp trực tiếp. – Leo

+0

@Leo - nó phụ thuộc vào trình biên dịch. GCC rất kém trong việc biên dịch nội tại NEON. LLVM của Apple là như vậy và trình biên dịch của Microsoft khá tốt. – BitBank

15

Cách tốt nhất để tối ưu hóa ứng dụng là sử dụng trình tạo hồ sơ tốt. Ý tưởng hay là viết mã suy nghĩ về hiệu quả, nhưng bạn cũng muốn tránh thay đổi nơi bạn "nghĩ" mã có thể chậm, điều này có thể làm mọi thứ tồi tệ hơn nếu bạn không chắc chắn 100%.

Tìm hiểu điểm nghẽn và tập trung vào những điểm đó.

Đối với tôi, hồ sơ là một quá trình lặp lại, bởi vì thường khi bạn sửa một nút cổ chai, những điều ít quan trọng khác thể hiện bản thân.

Ngoài việc định cấu hình SW, hãy kiểm tra loại hồ sơ HW nào có sẵn. Kiểm tra xem bạn có thể nhận được các chỉ số HW khác nhau, như nhớ cache, truy cập bộ nhớ bus, v.v. Điều này cũng rất hữu ích nếu biết xe buýt hoặc bộ nhớ cache của bạn là một nút cổ chai.

Gần đây tôi đã hỏi câu hỏi tương tự này và nhận được một số câu trả lời tốt: Looking for a low impact c++ profiler