โปรเซสเซอร์ / นาฬิกาที่เร็วขึ้นสามารถรันโค้ดเพิ่มเติมได้หรือไม่


9

ฉันกำลังเขียนโปรแกรมเพื่อทำงานบน ATmega 328 ซึ่งทำงานที่ 16Mhz (เป็น Arduino Duemilanove ถ้าคุณรู้ว่ามันเป็นชิป AVR)

ฉันมีกระบวนการขัดจังหวะที่ทำงานทุกๆ 100 microseconds เป็นไปไม่ได้ที่ฉันจะบอกได้ว่าต้องใช้ "โค้ด" เท่าไหร่คุณสามารถประมวลผลในหนึ่งวน 100 microseconds (ฉันกำลังเขียนใน C ซึ่งสันนิษฐานว่าถูกแปลงเป็นแอสเซมบลีแล้วเป็นภาพไบนารี?)

นอกจากนี้สิ่งนี้จะขึ้นอยู่กับความซับซ้อนของโค้ด (ตัวอย่างเช่นสายการบินหนึ่งอาจวิ่งช้ากว่าเส้นสั้น ๆ หลายเส้น)

ความเข้าใจของฉันถูกต้องหรือไม่ในกรณีที่โปรเซสเซอร์ของฉันมีอัตรานาฬิกาหรือ 16Mhz มีประสิทธิภาพ 16 ล้านรอบต่อวินาที (ซึ่งหมายถึง 16 รอบต่อไมโครวินาที 16,000,000 / 1,000 / 1,000); และถ้าฉันต้องการเพิ่มในวงวน 100 microsecond ของฉันการซื้อรุ่นที่เร็วกว่าเช่นรุ่น 72Mhz จะให้ 72 รอบต่อ microsecond (72,000,000 / 1,000 / 1,000)

ขณะนี้มันทำงานช้าไปนิดหน่อยนั่นคือมันใช้เวลานานกว่า 100 ไมโครวินาทีในการทำลูป (นานแค่ไหนยากเกินกว่าจะพูดได้ แต่มันค่อย ๆ ตกหลุม) และฉันอยากให้มันเพิ่มอีกหน่อยคือ นี่เป็นวิธีที่มีสติได้รับชิปเร็วขึ้นหรือฉันได้ไปบ้า?


.... ATmega328 ไม่ใช่ชิป ARM มันเป็น AVR
vicatcu

ไชโยแก้ไขแล้ว!
jwbensley

คำตอบ:


9

โดยทั่วไปจำนวนคำแนะนำในการประกอบอุปกรณ์ที่สามารถดำเนินการต่อวินาทีจะขึ้นอยู่กับคำสั่งผสมและจำนวนรอบของแต่ละประเภทคำสั่งใช้ (CPI) ในการดำเนินการ ในทางทฤษฎีคุณสามารถนับรหัสของคุณได้โดยดูที่ไฟล์ asm ที่ถอดประกอบและดูฟังก์ชั่นที่คุณเป็นห่วงนับจำนวนคำสั่งต่าง ๆ ทั้งหมดที่อยู่ในนั้น

ปัญหาของการพิจารณาจำนวนคำสั่งที่มีประสิทธิภาพต่อวินาทีนั้นรุนแรงขึ้นในตัวประมวลผลที่ซับซ้อนมากขึ้นเนื่องจากข้อเท็จจริงที่ว่าพวกมันถูกส่งไปและมีแคชและสิ่งที่ไม่ นี่ไม่ใช่กรณีสำหรับอุปกรณ์อย่างง่ายเช่น ATMega328 ซึ่งเป็นคำสั่งเดียวในโปรแกรมประมวลผลการบิน

สำหรับเรื่องที่ปฏิบัติได้สำหรับอุปกรณ์อย่างง่ายเช่น AVR คำตอบของฉันจะมากหรือน้อย "ใช่" การเพิ่มความเร็วนาฬิกาของคุณเป็นสองเท่าควรเป็นครึ่งหนึ่งของเวลาทำการของฟังก์ชั่นที่กำหนด อย่างไรก็ตามสำหรับ AVR มันจะไม่ทำงานเร็วกว่า 20MHz ดังนั้นคุณสามารถ "โอเวอร์คล็อก" Arduino ของคุณได้อีก 4MHz

คำแนะนำนี้ไม่ได้สรุปถึงโปรเซสเซอร์ที่มีคุณสมบัติขั้นสูง การเพิ่มความเร็วนาฬิกาเป็นสองเท่าบนโปรเซสเซอร์ Intel ของคุณจะไม่เพิ่มจำนวนคำสั่งที่ใช้งานต่อวินาทีเป็นสองเท่า (เนื่องจากการคาดคะเนผิดพลาดของสาขา


สวัสดีขอบคุณสำหรับคำตอบที่ให้ข้อมูลของคุณ! ฉันเคยเห็นหนึ่งในนี้ ( coolcomponents.co.uk/catalog/product_info.php?products_id=808 ) คุณบอกว่า AVR ไม่สามารถทำงานได้เร็วกว่า 20Mhz ทำไมล่ะ? ชิปบนบอร์ดด้านบน ( uk.farnell.com/stmicroelectronics/stm32f103rbt6/ ...... ) เป็น 72Mhz ARM ฉันคาดหวังว่าประสิทธิภาพที่เพิ่มขึ้นจากสิ่งนี้ในลักษณะที่ฉันได้อธิบายไว้ข้างต้น?
jwbensley

2
การเพิ่มความเร็วในการประมวลผลเป็นสองเท่าอาจไม่เพิ่มปริมาณงานคำสั่งเนื่องจากคุณอาจเริ่มต้นความเร็วเกินกว่าที่คำแนะนำสามารถเรียกได้จากแฟลช ณ จุดนี้คุณเริ่มกดปุ่ม "สถานะรอแฟลช" ที่ CPU หยุดชั่วคราวในขณะที่รอให้คำแนะนำมาถึงจากแฟลช ไมโครคอนโทรลเลอร์บางตัวรับรอบนี้โดยอนุญาตให้คุณรันโค้ดจาก RAM ซึ่งเร็วกว่า FLASH มาก
Majenko

@Majenko: ตลกเราทั้งคู่ทำจุดเดียวกันในเวลาเดียวกัน
Jason S

มันเกิดขึ้น ... ของคุณดีกว่าของฉัน :)
Majenko

1
ตกลงฉันได้ทำเครื่องหมายคำตอบของ Vicatcu ว่า "คำตอบ" ฉันรู้สึกว่ามันเหมาะสมที่สุดกับคำถามดั้งเดิมของฉันเกี่ยวกับความเร็วในการแสดงแม้ว่าคำตอบทั้งหมดนั้นยอดเยี่ยมมาก พวกเขาแสดงให้ฉันเห็นว่ามันเป็นวิชาที่กว้างกว่าที่ฉันรู้เป็นครั้งแรกดังนั้นพวกเขาจึงสอนให้ฉันมากมายและให้การวิจัยแก่ฉันดังนั้นขอบคุณทุกคน: D
jwbensley

8

คำตอบของ @ vicatcu นั้นค่อนข้างครอบคลุม สิ่งหนึ่งที่ควรทราบเพิ่มเติมคือ CPU อาจทำงานเป็นสถานะรอ (รอบ CPU ค้าง) เมื่อเข้าถึง I / O รวมถึงโปรแกรมและหน่วยความจำข้อมูล

ตัวอย่างเช่นเราใช้ TI F28335 DSP พื้นที่บางส่วนของ RAM เป็นสถานะ 0- รอสำหรับโปรแกรมและหน่วยความจำข้อมูลดังนั้นเมื่อคุณรันโค้ดใน RAM มันจะทำงานที่ 1 รอบต่อการเรียนการสอน (ยกเว้นสำหรับคำสั่งที่ใช้เวลามากกว่า 1 รอบ) เมื่อคุณเรียกใช้รหัสจากหน่วยความจำ FLASH (EEPROM ในตัวไม่มากก็น้อย) แต่มันไม่สามารถทำงานที่ 150MHz เต็มและช้าลงหลายครั้ง


เกี่ยวกับโค้ดขัดจังหวะความเร็วสูงคุณต้องเรียนรู้หลายสิ่งหลายอย่าง

ก่อนอื่นให้ทำความคุ้นเคยกับคอมไพเลอร์ของคุณ หากคอมไพเลอร์ทำงานได้ดีก็ไม่น่าจะช้ากว่าชุดประกอบที่เขียนด้วยมือสำหรับสิ่งส่วนใหญ่ (โดยที่ "ช้ากว่ามาก": ปัจจัย 2 จะโอเคโดยฉันปัจจัย 10 ไม่สามารถยอมรับได้) คุณต้องเรียนรู้วิธี (และเมื่อ) ใช้แฟล็กการเพิ่มประสิทธิภาพคอมไพเลอร์และทุกครั้งที่คุณควรมอง ที่เอาต์พุตของคอมไพเลอร์เพื่อดูว่ามันทำอย่างไร

บางสิ่งอื่น ๆ ที่คุณสามารถให้คอมไพเลอร์ทำเพื่อเร่งโค้ด:

  • ใช้ฟังก์ชั่นแบบอินไลน์ (จำไม่ได้ว่า C รองรับสิ่งนี้หรือถ้าเป็นเพียง C ++ - ism) ทั้งสำหรับฟังก์ชั่นขนาดเล็กและสำหรับฟังก์ชั่นที่จะถูกดำเนินการเพียงครั้งเดียวหรือสองครั้ง ข้อเสียคือฟังก์ชั่นอินไลน์ยากต่อการดีบักโดยเฉพาะอย่างยิ่งหากการปรับแต่งคอมไพเลอร์เปิดอยู่ แต่พวกเขาจะช่วยคุณประหยัดลำดับการโทร / ส่งคืนโดยไม่จำเป็นโดยเฉพาะอย่างยิ่งหากสิ่งที่เป็นนามธรรม "ฟังก์ชั่น" สำหรับวัตถุประสงค์ในการออกแบบแนวคิดมากกว่าการใช้รหัส

  • ดูคู่มือคอมไพเลอร์ของคุณเพื่อดูว่ามันมีฟังก์ชั่นที่แท้จริงหรือไม่ - นี่คือฟังก์ชั่นบิวอินในตัวคอมไพเลอร์ที่แมปกับคำสั่งแอสเซมบลีของโปรเซสเซอร์โดยตรง โปรเซสเซอร์บางตัวมีคำแนะนำการประกอบที่ทำสิ่งที่มีประโยชน์เช่น min / max / bit reverse และคุณสามารถประหยัดเวลาได้

  • หากคุณกำลังคำนวณตัวเลขให้แน่ใจว่าคุณไม่ได้เรียกฟังก์ชั่นคณิตศาสตร์ห้องสมุดโดยไม่จำเป็น เรามีกรณีหนึ่งที่รหัสนั้นคล้ายy = (y+1) % 4กับตัวนับที่มีระยะเวลา 4 คาดว่าคอมไพเลอร์จะใช้โมดูโล 4 เป็นบิต - และ มันเรียกว่าห้องสมุดคณิตศาสตร์แทน ดังนั้นเราจึงแทนที่ด้วยy = (y+1) & 3เพื่อทำสิ่งที่เราต้องการ

  • ทำความคุ้นเคยกับหน้าบิต twiddling แฮ็ก ฉันรับประกันว่าคุณจะใช้อย่างน้อยหนึ่งอย่างต่อไปนี้

คุณควรใช้อุปกรณ์ต่อพ่วงตัวจับเวลาของ CPU เพื่อวัดเวลาประมวลผลโค้ดส่วนใหญ่มีตัวจับเวลา / ตัวนับที่สามารถตั้งค่าให้ทำงานที่ความถี่สัญญาณนาฬิกาของ CPU จับสำเนาตัวนับที่จุดเริ่มต้นและจุดสิ้นสุดของรหัสที่สำคัญของคุณและคุณสามารถดูได้ว่าต้องใช้เวลานานเท่าใด หากคุณไม่สามารถทำเช่นนั้นได้อีกทางเลือกหนึ่งคือลดขาเอาต์พุตที่จุดเริ่มต้นของรหัสของคุณและเพิ่มมันที่ส่วนท้ายและดูผลลัพธ์นี้บนออสซิลโลสโคปเพื่อกำหนดเวลาดำเนินการ มีวิธีการแลกเปลี่ยนในแต่ละวิธี: ตัวจับเวลาภายใน / ตัวนับมีความยืดหยุ่นมากขึ้น (คุณสามารถใช้เวลาหลายสิ่ง) แต่ยากที่จะรับข้อมูลออกในขณะที่การตั้งค่า / การล้างขาออกจะมองเห็นได้ทันทีในขอบเขตและคุณสามารถบันทึกสถิติได้ เป็นการยากที่จะแยกแยะเหตุการณ์ต่าง ๆ

ในที่สุดก็มีเป็นทักษะที่สำคัญมากที่มาพร้อมกับประสบการณ์ - ทั้งทั่วไปและกับชุดประมวลผล / คอมไพเลอร์ที่เฉพาะเจาะจง: รู้เมื่อและเมื่อไม่เพิ่มประสิทธิภาพ โดยทั่วไปคำตอบคือไม่ปรับให้เหมาะสม การเสนอราคา Donald Knuth ได้รับการโพสต์บ่อยครั้งใน StackOverflow (มักเป็นเพียงส่วนสุดท้าย):

เราควรลืมเกี่ยวกับประสิทธิภาพเล็กน้อยพูดถึง 97% ของเวลา: การเพิ่มประสิทธิภาพก่อนวัยอันควรเป็นรากฐานของความชั่วร้ายทั้งหมด

แต่คุณอยู่ในสถานการณ์ที่คุณรู้ว่าคุณต้องทำการเพิ่มประสิทธิภาพบางอย่างดังนั้นถึงเวลากัดกระสุนและปรับให้เหมาะสม (หรือรับโปรเซสเซอร์ที่เร็วกว่าหรือทั้งสองอย่าง) อย่าไม่เขียน ISR ของคุณทั้งหมดในการชุมนุม นั่นเกือบจะเป็นหายนะที่รับประกันได้ถ้าคุณทำภายในไม่กี่เดือนหรือหลายสัปดาห์คุณจะลืมบางส่วนของสิ่งที่คุณทำและเพราะอะไรและรหัสมีแนวโน้มที่จะเปราะบางและยากที่จะเปลี่ยนแปลง มีแนวโน้มที่จะมีบางส่วนของรหัสของคุณซึ่งเป็นตัวเลือกที่ดีสำหรับการประกอบ

สัญญาณที่ว่าบางส่วนของรหัสของคุณเหมาะสำหรับการประกอบรหัส:

  • ฟังก์ชันที่มีรูทีนขนาดเล็กที่มีการกำหนดไว้อย่างดีซึ่งไม่น่าจะมีการเปลี่ยนแปลง
  • ฟังก์ชั่นที่สามารถใช้คำสั่งประกอบเฉพาะ (ขั้นต่ำ / สูงสุด / ขวากะ / ฯลฯ )
  • ฟังก์ชั่นที่เรียกหลายครั้ง (ทำให้คุณเพิ่มทวีคูณ: ถ้าคุณบันทึก 0.5usec ในการโทรแต่ละครั้งและได้รับการเรียก 10 ครั้งคุณจะประหยัด 5 usec ซึ่งมีความสำคัญในกรณีของคุณ)

เรียนรู้ฟังก์ชั่นการเรียกประชุมของคอมไพเลอร์ของคุณ (เช่นที่ทำให้ข้อโต้แย้งในการลงทะเบียนและการลงทะเบียนมันบันทึก / เรียกคืน) เพื่อให้คุณสามารถเขียนรูทีนแอสเซมบลีแบบ C-callable

ในโครงการปัจจุบันของฉันเรามี codebase ขนาดใหญ่ที่มีรหัสสำคัญที่ต้องทำงานในการขัดจังหวะ 10kHz (คุ้นเคยกับ 100usec - sound คุ้นหู?) และมีฟังก์ชั่นมากมายที่เขียนไว้ในชุดประกอบ สิ่งที่เป็นคือสิ่งต่าง ๆ เช่นการคำนวณซีอาร์ซีคิวซอฟต์แวร์ ADC กำไร / ชดเชยค่าชดเชย

โชคดี!


คำแนะนำที่ดีเกี่ยวกับเทคนิคการวัดเวลาดำเนินการเชิงประจักษ์
vicatcu

อีกคำตอบที่ยอดเยี่ยมสำหรับคำถามของฉันขอบคุณ Jason S สำหรับความรู้อันน่าทึ่งนี้! สองสิ่งที่ชัดเจนหลังจากอ่านข้อความนี้; ประการแรกฉันสามารถเพิ่มการขัดจังหวะจากทุก ๆ 100uS เป็น 500uS เพื่อให้รหัสมีเวลามากขึ้นในการดำเนินการฉันรู้ว่าตอนนี้มันไม่ได้เป็นประโยชน์กับฉันอย่างรวดเร็ว ประการที่สองฉันคิดว่ารหัสของฉันอาจไม่มีประสิทธิภาพเกินไปด้วยเวลาขัดจังหวะที่ยาวนานขึ้นและรหัสที่ดีกว่ามันอาจจะใช้ได้ทั้งหมด Stackoverflow เป็นที่ที่ดีกว่าในการโพสต์โค้ดดังนั้นฉันจะโพสต์ที่นั่นและวางลิงค์ไว้ที่นี่หากใครต้องการดูและให้คำแนะนำใด ๆ โปรดทำ: D
jwbensley

5

สิ่งอื่นที่ควรทราบ - อาจมีการเพิ่มประสิทธิภาพบางอย่างที่คุณสามารถทำได้เพื่อทำให้โค้ดของคุณมีประสิทธิภาพมากขึ้น

ตัวอย่างเช่น - ฉันมีรูทีนที่ทำงานจากการขัดจังหวะตัวจับเวลา รูทีนต้องทำให้เสร็จภายใน 52µS และต้องผ่านหน่วยความจำจำนวนมากในขณะที่กำลังทำ

ฉันจัดการความเร็วที่เพิ่มขึ้นอย่างมากโดยการล็อคตัวแปรตัวนับหลักเพื่อลงทะเบียนด้วย (บน µC & คอมไพเลอร์ของฉัน - ต่างจากของคุณ):

register unsigned int pointer asm("W9");

ฉันไม่ทราบรูปแบบสำหรับคอมไพเลอร์ของคุณ - RTFM แต่จะมีบางสิ่งที่คุณสามารถทำได้เพื่อทำให้กิจวัตรของคุณเร็วขึ้นโดยไม่ต้องเปลี่ยนมาใช้แอสเซมบลี

ต้องบอกว่าคุณอาจจะทำได้ดีกว่าการเพิ่มประสิทธิภาพกิจวัตรประจำวันของคุณให้ดีขึ้นกว่าคอมไพเลอร์ดังนั้นการเปลี่ยนมาใช้แอสเซมบลีอาจทำให้คุณเพิ่มความเร็วได้มากขึ้น


ฮ่า ๆ ผม "พร้อมกัน" ความเห็นเกี่ยวกับคำตอบของตัวเองเกี่ยวกับการปรับแต่งและลงทะเบียนผู้ประกอบการจัดสรร :)
vicatcu

ถ้ามันสละ 100us บนหน่วยประมวลผล 16 MHz - มันเห็นได้ชัดมากสวยดังนั้นว่ามากของรหัสที่จะเพิ่มประสิทธิภาพ ฉันได้ยินมาว่าคอมไพเลอร์ในปัจจุบันผลิตโค้ดประมาณ 1.1 เท่าของแอสเซมบลีที่พอดีด้วยมือ โดยรวมแล้วไม่คุ้มค่าสำหรับงานประจำขนาดใหญ่เช่นนี้ สำหรับการโกนลด 20% ฟังก์ชั่น 6 สายบางที ...
DefenestrationDay

1
ไม่จำเป็นต้อง ... มันอาจเป็นโค้ดเพียง 5 บรรทัดในการวนซ้ำ และก็ไม่ได้เกี่ยวกับรหัสขนาดแต่เกี่ยวกับรหัสประสิทธิภาพ คุณอาจสามารถเขียนรหัสต่าง ๆ ทำให้ทำงานเร็วขึ้น ฉันรู้ว่ารูทีนขัดจังหวะฉันทำ ตัวอย่างเช่นเสียสละขนาดเพื่อความเร็ว โดยการเรียกใช้รหัสเดียวกัน 10 ครั้งตามลำดับคุณประหยัดเวลาในการมีรหัสในการทำลูป - และตัวแปรตัวนับที่เกี่ยวข้อง ใช่รหัสนั้นยาวกว่า 10 เท่า แต่มันก็ทำงานได้เร็วขึ้น
Majenko

สวัสดี Majenko ฉันไม่รู้จักการชุมนุม แต่ฉันคิดเกี่ยวกับการเรียนรู้และคิดว่า Arduino จะมีความซับซ้อนน้อยกว่าคอมพิวเตอร์เดสก์ท็อปของฉันดังนั้นนี่อาจเป็นเวลาที่ดีในการเรียนรู้โดยเฉพาะอย่างยิ่งฉันอยากรู้ เพิ่มเติมเกี่ยวกับสิ่งที่เกิดขึ้นและระดับที่ต่ำกว่า อย่างที่คนอื่นพูดฉันจะไม่เขียนสิ่งใหม่ทั้งหมดเพียงบางส่วน ความเข้าใจของฉันคือฉันสามารถดรอป ASM ภายใน C ได้ถูกต้องนี่เป็นวิธีที่จะทำให้ C และ ASM ผสมกันได้หรือไม่ ฉันจะโพสต์บน stackoverflow สำหรับข้อมูลเฉพาะหลังจากแนวคิดทั่วไป
jwbensley

@javano: ใช่ คุณสามารถดรอป ASM ภายใน C ระบบหลายตัวถูกเขียนแบบนั้น - ในส่วนผสมของ C และแอสเซมบลี - ส่วนใหญ่เป็นเพราะมีบางสิ่งที่ไม่สามารถทำได้ในคอมไพเลอร์ C ดั้งเดิมที่มีอยู่ เวลา. อย่างไรก็ตามคอมไพเลอร์ C ที่ทันสมัยเช่น gcc (ซึ่งเป็นคอมไพเลอร์ที่ใช้โดย Arduino) ตอนนี้จัดการได้มากที่สุดและในหลาย ๆ กรณีทุกสิ่งที่ต้องใช้ภาษาแอสเซมบลี
davidcary
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.