Viết thuật toán DSP trực tiếp bằng C hay lắp ráp? [đóng cửa]


18

Tôi đang làm việc trên một dự án DSP (lọc IIR) trên bộ xử lý tín hiệu số Thiết bị analog (BF706) với bộ trình biên dịch đi kèm với nó, CrossCore Studio. Nó có một số ví dụ cho các công cụ DSP đơn giản như bộ lọc FIR và IIR và các chức năng thư viện cho nó. Hướng dẫn xử lý mô tả tập lệnh lắp ráp và không nhận xét về C.

Câu hỏi của tôi phát sinh từ ứng dụng cụ thể này, nhưng tôi nghĩ có một cách thực hành tốt nhất mà các nhà phát triển DSP tuân theo. Vì vậy, tôi sẽ đóng khung nó một cách chung chung:

Những gì tôi đã nhận ra qua các ví dụ đi kèm với DSP này, là nếu tôi muốn sử dụng các mạch được thiết kế cho các ứng dụng DSP, tôi cần lập trình trong lắp ráp để chạy trực tiếp các hướng dẫn đó. (Như nhân và thêm, v.v.) Câu hỏi của tôi là Tôi chỉ lập trình trong C, trình biên dịch (cũng đến từ công ty chip DSP) sẽ tối ưu hóa nó cho DSP đó và sử dụng các khả năng của nó chứ? Hay tôi thực sự cần phải viết các thói quen DSP trực tiếp trong lắp ráp?


17
Tôi đã dành nhiều năm để viết lắp ráp cho ADSP-21xx (và lắp ráp và C cho Blackfin, sau này.) Bạn không tiết lộ những gì bạn đang sử dụng, vì vậy mọi câu trả lời sẽ là một phỏng đoán và ý kiến ​​hơn bất kỳ điều gì khác. Nhưng bộ xử lý DSP của AD là những thứ tốt và rất khó để người viết trình biên dịch C có thể lấp đầy đường ống một cách chính xác. Tôi có hai thập kỷ kinh nghiệm trong lĩnh vực này (bao gồm một số kinh nghiệm rất khiêm tốn khi viết trình biên dịch C) và cho đến khi tôi ngừng viết mã (một vài năm trước), trình biên dịch C không thể tiến gần đến mã hóa tay. Nhưng những gì bạn làm phụ thuộc vào mục tiêu của bạn.
jonk

1
@jonk hy vọng bạn sẽ viết câu trả lời cho câu hỏi này - Tôi chỉ từng thực hiện một dự án DSP Blackfin khó tính, nhưng tôi có những kỷ niệm đẹp về một số bản hack hiệu suất cần thiết :)
pericynthion

6
@pericynthion Không, tôi không thể tưởng tượng việc viết câu trả lời cho nó trừ khi OP nói nhiều hơn về DSP và các mục tiêu dự án cụ thể. Nếu không, đó sẽ là những ý kiến ​​mơ hồ, không có căn cứ có thể rất đúng hoặc rất sai tùy thuộc vào những gì OP sau đó đã viết về nó. Vì vậy, tôi sẽ chỉ chờ đợi.
jonk

1
Nếu bạn muốn nó chạy nhanh nhất, bạn hãy tối ưu hóa nó trong lắp ráp. Đó là một thời gian \ tiền đánh đổi. Nếu bạn biết cách viết C tốt, bạn có thể đi gần hết.
Điện áp tăng đột biến

2
Tôi không chắc chắn về DSP nhưng đối với hầu hết các bộ vi xử lý, bạn có thể sử dụng nội tại nằm giữa trình biên dịch mã và trình biên dịch.
Maciej Piechotka

Câu trả lời:


20

Sẽ tốt hơn nếu thuật toán của bạn được triển khai bằng ngôn ngữ cấp cao hơn (mà C được so sánh với lắp ráp), ngay cả khi cuối cùng bạn có kế hoạch thực hiện mọi thứ trong lắp ráp.

  • rất có thể, bạn thậm chí sẽ không cần lắp ráp . Nếu mã được tạo bởi trình biên dịch của bạn đáp ứng các mục tiêu thiết kế của bạn, công việc của bạn đã hoàn thành.

  • nếu không, bạn sẽ không bắt đầu mã hóa lắp ráp từ đầu . Hãy để trình biên dịch tạo mã ban đầu cho bạn và sử dụng nó làm cơ sở cho phiên bản lắp ráp được tối ưu hóa của bạn.

  • sau này, khi bạn cần kiểm tra mã lắp ráp được tối ưu hóa của mình , bạn sẽ rất vui khi có phiên bản C. Thay vì tính toán thủ công đầu ra chính xác cho dữ liệu đầu vào thử nghiệm của bạn, bạn chỉ có thể cung cấp dữ liệu đầu vào đó cho việc triển khai C chưa được tối ưu hóa của mình, sau đó kiểm tra xem tổ hợp có tạo ra chính xác đầu ra sau khi tối ưu hóa bạn đã thực hiện không.

Nếu, sau một vài năm, một nhà phát triển mới sẽ cần phải sửa đổi thuật toán của bạn và tất cả những gì họ có trong tay là một mã lắp ráp được tối ưu hóa cao, có khả năng cao họ sẽ phải bắt đầu lại từ đầu.


23

Nếu người viết trình biên dịch đặt một số nỗ lực vào việc tối ưu hóa nó cho mục tiêu đó, thì ít nhất nó sẽ sử dụng một số hướng dẫn / kiến ​​trúc DSP đặc biệt. Nhưng đối với hiệu suất cao nhất, nó sẽ không bao giờ tốt như lắp ráp bằng tay. Nó có thể đủ tốt, mặc dù - phụ thuộc vào ứng dụng của bạn.

Các lựa chọn thay thế khác bao gồm:

  1. Viết phần lớn chương trình của bạn bằng C và chỉ phần số quan trọng nhất trong phần lắp ráp.
  2. Viết chương trình bằng C và sử dụng các thư viện do nhà sản xuất hoặc bên thứ ba cung cấp - nếu bạn đang thực hiện các tác vụ DSP phổ biến như FFT, bộ lọc FIR / IIR, v.v ... ai đó có thể đã viết mã máy được điều chỉnh bằng tay để thực hiện, vì vậy bạn có thể sử dụng nó (bạn có thể phải trả tiền cho nó) và liên kết nó với ứng dụng của bạn.

Thông thường, các nhà cung cấp DSP sẽ cung cấp mã nguồn cho các chức năng phổ biến. Nếu mã của họ là "đủ tốt", bạn có thể thả nó ngay vào. Nếu nó không hoàn toàn đúng, bạn phải điều chỉnh nó. Tôi đã phải thực hiện một lớp FFT vài năm trước, để có được một FFT thực sự chỉ có tần số. Có một mẹo cho phép bạn thực hiện FFT thực 2 điểm dưới dạng FFT phức tạp điểm N, nhưng sau đó bạn phải thực hiện lần cuối qua đầu ra phức tạp để khôi phục dữ liệu tần số thực. Thiết bị analog không có trường hợp cụ thể đó trong mã ví dụ của họ.
John R. Strohm

21

Tối ưu hóa sớm là gốc rễ của mọi tội lỗi. - Donald Knuth

Khi bạn thấy rằng bạn không nhận đủ hiệu suất từ ​​mã của mình, trước tiên hãy lập hồ sơ cho chương trình của bạn, tìm các nút thắt cổ chai, phân tích các yêu cầu về hiệu suất của bạn và chỉ sau đó bắt đầu thực hiện tối ưu hóa. Viết mã lắp ráp là giải pháp cuối cùng.

Câu hỏi của tôi là nếu tôi chỉ lập trình trong C, trình biên dịch (cũng đến từ công ty chip DSP) sẽ tối ưu hóa nó cho DSP đó và sử dụng các khả năng của nó?

Có, trình biên dịch C có thể thực hiện một số lượng tối ưu hợp lý. Nhưng điều này phụ thuộc vào chất lượng của trình biên dịch. Thông thường, một con người có thể viết mã lắp ráp nhanh hơn mã C được biên dịch. Với chi phí lớn của nỗi đau và đau khổ của con người, đó là.

Hay tôi thực sự cần phải viết các thói quen DSP trực tiếp trong lắp ráp?

Đầu tiên viết bằng C, sau đó hồ sơ, sau đó quyết định xem bạn có cần viết trong lắp ráp không. Hy vọng, bạn sẽ không cần lắp ráp.


20
Trong lập trình chung, đây chắc chắn là một lời khuyên tốt, nhưng DSP thì hơi khác một chút - nếu OP thực sự muốn sử dụng DSP hiệu quả thì có lẽ sẽ cần một số mã viết tay ở đâu đó dọc theo đường. Và trên thực tế với các dự án DSP đôi khi bạn thậm chí muốn bắt đầu bằng cách viết hạt nhân số lõi đó, để xác thực rằng bộ xử lý sẽ phù hợp với nhiệm vụ trong tay.
pericynthion

11
Tuyên bố kết luận của bạn là lời khuyên chung tốt. Nhưng nó hơi nhạt khi xem xét các chi tiết cụ thể của AL DSP AD DSP. Tôi không cho rằng bạn đã từng kiểm tra chúng.
jonk

18

DSP của bạn sẽ được quảng cáo với MAC duy trì tối đa, giả sử tất cả các đường ống đã được lấp đầy. Đó rõ ràng là một giới hạn trên cho những gì có thể đạt được. Bạn biết có bao nhiêu MAC bộ lọc của bạn và xử lý khác sẽ mất, từ phân tích của bạn. Đặt mục tiêu có cái đầu tiên ít nhất gấp đôi lần thứ hai, vì bạn sẽ không thể giữ cho lõi DSP hoạt động tối đa. Giống như bạn sẽ không cố gắng lấp đầy một nguồn tài nguyên trên 70% (PAR trở nên rất chậm trên mức đó), sự phát triển có thể trở nên rất chậm khi cố gắng loại bỏ một số MAC lý thuyết cuối cùng ra khỏi DSP.

Bạn sẽ mã hóa toàn bộ ứng dụng của mình trong C. Thật không thực tế khi viết tất cả những thứ cần thiết, bổ sung trong trình biên dịch chương trình, kiểm tra nội dung và khả năng hiển thị, vệ sinh, v.v. Viết phiên bản C của bộ lọc thử nghiệm. Viết phiên bản trình biên dịch của cùng một bộ lọc, để xác minh rằng trên thực tế bạn có thể viết trình biên dịch chương trình biên dịch mã cho con thú này.

Bây giờ làm một số thời gian. Sử dụng một RTOS được phê duyệt bởi nhà cung cấp. So sánh thời gian chạy của mô đun trình biên dịch thử nghiệm của bạn với phiên bản C. Nếu họ ở trong một vài phần trăm, hãy tiếp tục. Nếu nó tăng gấp ba, thì hãy đọc tài liệu, kiểm tra nhà cung cấp và tìm hiểu lý do tại sao trình biên dịch không điều chỉnh nó. Bạn có thể cần học cách viết hương vị của C nhiều như đặt cờ trình biên dịch chính xác, sẽ nhanh hơn để tìm ra cách điều khiển trình biên dịch đúng hơn là viết lại mọi thứ trong trình biên dịch chương trình.

Bạn đã thực hiện tất cả điều này trước khi cam kết với DSP, cho chuỗi công cụ.

Khi bạn có một chuỗi công cụ bạn có thể làm việc với, một trình biên dịch bạn có thể điều chỉnh để đạt gần mức tối đa, DSP với một khoảng trống thời gian còn lại, sau đó bạn có thể tin tưởng một cách hợp lý rằng rất ít phần của bộ mã của bạn sẽ cần được đưa vào lắp ráp để hoàn thành công việc.


7

Mặc dù tôi đã trả lời câu hỏi này rồi, tôi sẽ thêm một câu trả lời khác để minh họa một quan điểm khác:

Viết bằng C, đọc lắp ráp!

Vì vậy, thay vì viết trong assembly, bạn sẽ viết logic bằng C, cẩn thận đảm bảo rằng đầu ra của trình biên dịch mã C là tối ưu. Bạn thường có thể thực hiện một số thủ thuật nhất định trên mã C để ảnh hưởng đến đầu ra của trình biên dịch chương trình. Sử dụng các hàm nội tuyến tĩnh khi nó có ý nghĩa. Nếu bạn cần sử dụng một số hướng dẫn đặc biệt mà DSP hỗ trợ, hãy thực hiện trừu tượng hóa hàm nội tuyến tĩnh của lệnh đặc biệt và gọi lệnh đặc biệt bằng cách sử dụng trừu tượng hóa.

Mặc dù tôi phải nói rằng tôi chưa bao giờ lập trình DSP, cách tiếp cận viết mã C này trong khi quan sát cẩn thận lắp ráp đã biên dịch đã giúp tôi rất tốt trên các máy x86. Thật vậy, trên thực tế, tôi chưa bao giờ phải viết bất cứ điều gì trong hội đồng để có được hiệu suất tốt nhất có thể. Tôi sẽ thay vì tối ưu hóa mã lắp ráp sửa đổi mã C theo cách mà lắp ráp là tối ưu.

Tất nhiên, điều này phụ thuộc vào trình biên dịch C tốt có sẵn. Đối với x86 trình biên dịch như vậy có sẵn (bạn thường phải chỉ định mức tối ưu hóa cao hơn mặc định). Đối với DSP, tôi thực sự không biết liệu trình biên dịch có tốt như vậy không.

Lợi ích của phương pháp này là bạn có một cơ sở mã di động duy nhất, được tối ưu hóa để mang lại sự lắp ráp tối ưu cho một DSP nhất định, nhưng nó cũng hoạt động nếu DSP được thay đổi thành thứ khác. Tất nhiên bạn có thể phải điều chỉnh một chút mã C để có được hiệu suất tốt nhất có thể trên DSP mới.


Tôi có một câu hỏi về điều này: Tôi làm việc trên bộ xử lý STM32F4 Cortex-M4 và tôi sử dụng các thư viện CMSIS / Cube. Tôi cũng sử dụng cờ -O3 của trình biên dịch, bởi vì nó đã chứng minh cách hiệu quả hơn bất cứ thứ gì tôi có thể sản xuất. Vấn đề là lắp ráp được biên dịch luôn quá hỗn loạn để phân tích chính xác. Bạn luôn luôn biên dịch mà không tối ưu hóa trình biên dịch? Hoặc bạn có quản lý để thực hiện hội nghị đêm trước, nếu nó ở khắp mọi nơi?
Florent

2
@FlorentEcochard: Nếu trình lập trình biên dịch không thể hiểu được bởi một lập trình viên, có lẽ nó tốt hơn trình biên dịch mà lập trình viên này có thể viết. Là câu trả lời trực tiếp cho câu hỏi của bạn: sử dụng tối ưu hóa tối đa và phân tích thủ công trình biên dịch, các phần khó có thể mang tính giáo dục.
pasaba por aqui

4

Nói chung, không cần thiết phải ghi các nguồn biên dịch nếu:

  • bạn tối ưu hóa C trong các phần quan trọng: sử dụng tốt từ khóa "đăng ký", chức năng nội tuyến, ...
  • có thể là một số chức năng của chương trình C sử dụng khối asm

Điều đó có nghĩa là xem xét thủ công trình biên dịch được tạo bởi trình biên dịch C (cho các phần quan trọng) và sửa đổi nguồn cho đến khi đủ mức tối ưu hóa.


Hầu như tất cả các trình biên dịch hiện đại đều bỏ qua từ khóa "đăng ký", bất kể nền tảng. Sử dụng nó rất khó có thể dẫn đến mã tốt hơn.
Kef Schecter

@KefSchecter: không chỉ họ tính đến gợi ý đăng ký, ngày nay họ thậm chí còn cho phép chọn đăng ký sẽ được sử dụng: gcc.gnu.org/onlinesocs/gcc-6.1.0/gcc/ trộm
pasaba por aqui

1
@KefSchecter: ngoại trừ trình biên dịch được viết cho các thiết bị nhúng, trong đó đây là một từ khóa rất quan trọng nếu bạn đang lập trình trên kim loại trần.
vsz

@pasabaporaqui: Tôi quên mất cú pháp đó. Nhưng nếu bạn không chỉ định tên đăng ký - nói cách khác, nếu bạn sử dụng nó theo cách tiêu chuẩn ISO - tôi cá là GCC sẽ bỏ qua nó.
Kef Schecter

3

Tôi muốn nói ở đây rằng nếu bạn thực hiện các bộ lọc FIR / IIR, thì thuật toán bạn sử dụng (thuật toán tầm thường so với biến đổi Fourier nhanh (FFT)) quan trọng hơn nhiều so với ngôn ngữ bạn sử dụng (C so với lắp ráp).

Tôi sẽ viết FFT trong hội đồng? Chắc là không.

Tôi có thể tự viết FFT không? Câu trả lời cho điều này cũng có thể là không, vì FFT đã được triển khai nhiều lần rồi. Vì vậy, rất có thể bạn sẽ tìm thấy một số thư viện đã thực hiện FFT. Xem xét rằng C là một ngôn ngữ di động trong khi lắp ráp thì không, bạn sẽ có nhiều khả năng tìm thấy các thư viện hiện có đã được triển khai trong C.

Nếu bạn muốn hiệu suất cao nhất có thể, rõ ràng bạn có thể điều chỉnh thuật toán FFT để hoạt động nhanh nhất có thể trong ngôn ngữ lắp ráp. Nhưng tôi không thực sự tin rằng nó có ý nghĩa để làm điều đó ngoại trừ trong những trường hợp rất đặc biệt.


2

Quan điểm riêng của tôi FWIW là bất cứ khi nào bạn muốn tốc độ / hiệu quả / thông lượng tối đa / bất cứ điều gì, trình biên dịch là bạn của bạn, miễn là bạn thành thạo. Một trình biên dịch bị câm; nó "chỉ biết" những gì tác giả của nó nghĩ để lập trình vào nó và tác giả của nó hoàn toàn không biết ứng dụng của bạn.

Tôi phải thừa nhận, tôi đã yêu thích trình biên dịch từ đầu thập niên 80 8 bit (không giống với MCU hiện đại ở nhiều khía cạnh) trong đó việc học "mã máy" là điều kiện tiên quyết để có được bất kỳ hiệu suất hữu ích nào từ chúng, nhưng tôi nghĩ vai trò của nó vẫn còn như các cách để chương trình cho hiệu quả tối đa. Thêm vào đó, nó rất bổ ích khi bạn có thể đưa vào tất cả các loại phím tắt tối ưu hóa mà trình biên dịch sẽ không nghĩ tới, bởi vì trình biên dịch hoàn toàn không thể nghĩ ra.

C đoán là ổn. Nhưng nếu bạn thực sự biết những gì bạn muốn máy của bạn làm ở cấp độ phần cứng, hãy đi lắp ráp.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.