ทำไมมัลติเธรดถึงเป็นที่ต้องการสำหรับการปรับปรุงประสิทธิภาพ?


23

ฉันมีคำถามเกี่ยวกับสาเหตุที่โปรแกรมเมอร์ดูเหมือนว่าจะรักการทำงานพร้อมกันและโปรแกรมแบบมัลติเธรดโดยทั่วไป

ฉันกำลังพิจารณา 2 วิธีหลักที่นี่:

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

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

ฉันได้ทดสอบโปรแกรมแบบมัลติเธรดและโปรแกรม async บนเครื่องเก่าด้วย Intel quad-core ที่ไม่ได้มีตัวควบคุมหน่วยความจำภายในซีพียูหน่วยความจำได้รับการจัดการทั้งหมดโดยเมนบอร์ดในกรณีนี้การแสดงที่น่ากลัวกับ แอ็พพลิเคชันแบบมัลติเธรดแม้จำนวนเธรดที่ค่อนข้างต่ำเช่น 3-4-5 อาจเป็นปัญหาแอ็พพลิเคชันไม่ตอบสนองและเป็นเพียงช้าและไม่เป็นที่พอใจ

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

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

ในซีพียูสมัยใหม่สถานการณ์มันไม่ได้แตกต่างกันจริงๆตัวควบคุมหน่วยความจำที่รวมเข้าด้วยกัน แต่ประเด็นของฉันคือซีพียู x86 นั้นเป็นเครื่องอนุกรมและตัวควบคุมหน่วยความจำทำงานแบบเดียวกับเครื่องเก่าที่มีตัวควบคุมหน่วยความจำภายนอกบนเมนบอร์ด . การสลับบริบทยังคงมีค่าใช้จ่ายที่เกี่ยวข้องในแอปพลิเคชันของฉันและความจริงที่ว่าตัวควบคุมหน่วยความจำที่รวมเข้าด้วยกันหรือ CPU ตัวใหม่มีแกนประมวลผลมากกว่า 2 คอร์มันไม่ได้ต่อรองราคาสำหรับฉัน

สำหรับสิ่งที่ฉันมีประสบการณ์วิธีการทำงานพร้อมกันนั้นดีในทางทฤษฎี แต่ไม่ดีในทางปฏิบัติด้วยโมเดลหน่วยความจำที่กำหนดโดยฮาร์ดแวร์มันยากที่จะใช้กระบวนทัศน์นี้ได้ดีมันยังแนะนำปัญหามากมายตั้งแต่การใช้งาน ของโครงสร้างข้อมูลของฉันเพื่อเข้าร่วมหลายกระทู้

อีกทั้งกระบวนทัศน์ทั้งสองไม่ได้เสนอการรักษาความปลอดภัยใด ๆ เมื่องานหรืองานจะทำในเวลาที่กำหนดทำให้พวกเขาคล้ายกันจริงๆจากมุมมองการทำงาน

ตามรุ่นหน่วยความจำ X86 ทำไมคนส่วนใหญ่แนะนำให้ใช้การทำงานพร้อมกันกับ C ++ และไม่ใช่แค่วิธีการแบบอะซิงโครนัส? ทำไมไม่ลองพิจารณาสถานการณ์กรณีที่เลวร้ายที่สุดของคอมพิวเตอร์ซึ่งการสลับบริบทอาจมีราคาแพงกว่าการคำนวณเอง?


2
วิธีหนึ่งในการเปรียบเทียบคือดูที่โลก JavaScript หากไม่มีการทำเกลียวและทุกอย่างไม่ตรงกันโดยใช้การโทรกลับ มันใช้งานได้ แต่มันมีปัญหาของตัวเอง
Gort the Robot

2
@StevenBurnap คุณเรียกคนทำงานเว็บว่าอย่างไร
user16764

2
"แม้จำนวนเธรด 3-4-5 ค่อนข้างต่ำอาจเป็นปัญหาแอปพลิเคชันไม่ตอบสนองและช้าและไม่เป็นที่พอใจ" => อาจเป็นเพราะการออกแบบ / การใช้เธรดไม่เหมาะสม โดยทั่วไปคุณจะพบสถานการณ์แบบนั้นเมื่อเธรดของคุณทำการแลกเปลี่ยนข้อมูลซึ่งในกรณีนี้การทำมัลติเธรดอาจไม่ใช่คำตอบที่ถูกต้องหรือคุณอาจต้องแบ่งพาร์ติชันข้อมูลใหม่
assylias

1
@assylias หากต้องการดูการชะลอตัวลงอย่างมีนัยสำคัญในเธรด UI บ่งชี้ว่ามีการล็อคข้ามเธรดจำนวนมากเกินไป คุณมีการนำไปใช้ที่ไม่ดีหรือคุณกำลังพยายามตอกหมุดสี่เหลี่ยมลงในรูกลม
Evan Plaice

5
คุณพูดว่า "โปรแกรมเมอร์ดูเหมือนจะรักการทำงานพร้อมกันและโปรแกรมแบบมัลติเธรดโดยทั่วไป" ฉันสงสัยว่า ผมจะบอกว่า "โปรแกรมเมอร์เกลียดมัน" ... แต่มักจะเป็นสิ่งที่มีประโยชน์เท่านั้นที่จะทำ ...
โยฮันเน

คำตอบ:


34

คุณมีหลายคอร์ / ผู้สนับสนุนใช้พวกเขา

Async เป็นวิธีที่ดีที่สุดสำหรับการทำการประมวลผลแบบ จำกัด IO ที่หนักหน่วง แต่การประมวลผลที่เชื่อมโยงกับ CPU จำนวนมากเป็นอย่างไร

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

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

เช่นเดียวกันในแอปพลิเคชันที่มีหลายกระบวนการสามารถส่งงานผ่านการส่งข้อความ (เช่น IPC, ซ็อกเก็ต ฯลฯ ) ไปยังกระบวนการย่อยที่ออกแบบมาเพื่อประมวลผลงานโดยเฉพาะ

ในทางปฏิบัติรหัส async และ multi-threaded / process มีข้อดีและข้อเสียต่างกัน

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

ตัวอย่าง:

  • ที่เก็บข้อมูล (เช่น Amazon S3, Google Cloud Drive) ถูกผูกไว้กับ CPU
  • เว็บเซิร์ฟเวอร์ถูกผูกไว้กับ IO (Amazon EC2, Google App Engine)
  • ฐานข้อมูลเป็นทั้ง CPU ที่ถูกผูกไว้สำหรับการเขียน / การจัดทำดัชนีและ IO ที่ถูกผูกไว้สำหรับการอ่าน

เพื่อนำไปสู่มุมมอง ...

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

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

แอปพลิเคชันที่ดีที่สุดมักจะใช้ทั้งสองอย่างร่วมกัน ตัวอย่างเช่นเว็บแอพอาจใช้ nginx (เช่น async เธรดเดี่ยว) เป็นโหลดบาลานเซอร์เพื่อจัดการฝนตกหนักของคำขอขาเข้าเว็บเซิร์ฟเวอร์ async ที่คล้ายกัน (เช่น Node.js) เพื่อจัดการกับคำขอ HTTP และชุดเซิร์ฟเวอร์มัลติเธรด จัดการกับการอัปโหลด / การสตรีม / การเข้ารหัสเนื้อหา ฯลฯ ...

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

มันเป็นไปตามแนวความคิดเดียวกันที่แสดงให้เห็นถึงการใช้ GPU และ CPU ในแบบคู่ขนาน ระบบพิเศษสองระบบที่ทำงานในคอนเสิร์ตสามารถปรับปรุงได้ดีกว่าวิธีเสาหินเดี่ยว

ไม่ดีกว่าเพราะทั้งคู่มีประโยชน์ ใช้เครื่องมือที่ดีที่สุดสำหรับงาน

ปรับปรุง:

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

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

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

Update2:

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


ทำไมโปรแกรมเมอร์ควรไปหลายขั้นตอน? ฉันหมายความว่าฉันคิดว่าด้วยกระบวนการมากกว่า 1 ขั้นตอนคุณต้องมีการสื่อสารระหว่างกระบวนการบางอย่างที่สามารถเพิ่มค่าใช้จ่ายที่สำคัญได้นี่เป็นสิ่งที่เป็นวิธีการเขียนโปรแกรม windows แบบเก่าหรือไม่? เมื่อไหร่ที่ฉันควรไปหลายขั้นตอน ขอบคุณสำหรับการตอบกลับของคุณภาพที่ดีจริงๆของสิ่งที่ async และมัลติเธรดเป็นสิ่งที่ดี
user1849534

1
คุณกำลังสมมติว่าการสื่อสารระหว่างกระบวนการจะเพิ่มค่าใช้จ่ายโดยรวม อย่างไรก็ตามหากสถานะการประมวลผลไม่เปลี่ยนรูปหรือเพียงต้องการจัดการกับ synchroniztion เมื่อเริ่มต้น / เสร็จสิ้น มันจะมีประสิทธิภาพมากขึ้นในการคลี่คลายภารกิจที่ขนานกันมากขึ้น รูปแบบของนักแสดงเป็นตัวอย่างที่ดีและถ้าคุณไม่ได้อ่านเกี่ยวกับมัน - มันคุ้มค่าที่จะอ่าน akka.io
sylvanaar

1
@ user1849534 หลายเธรดสามารถพูดคุยกันผ่านหน่วยความจำที่แชร์ + การล็อกหรือ IPC การล็อกนั้นง่ายกว่า แต่ยากกว่าที่จะทำการดีบั๊กถ้าคุณทำผิดพลาด (เช่นพลาดการล็อค IPC นั้นดีที่สุดถ้าคุณมีเธรดผู้ทำงานจำนวนมากเนื่องจากการล็อกไม่ได้ปรับขนาดได้ดี ไม่ว่าจะด้วยวิธีใดหากคุณใช้วิธีการแบบมัลติเธรดสิ่งสำคัญคือการสื่อสาร / การซิงโครไนซ์ข้ามเธรดให้น้อยที่สุด (เช่นเพื่อลดค่าใช้จ่าย)
Evan Plaice

1
@ akka.io คุณพูดถูก การเปลี่ยนไม่ได้เป็นวิธีหนึ่งในการลด / กำจัดค่าใช้จ่ายในการล็อค แต่คุณยังต้องเสียค่าใช้จ่ายในการสลับบริบท หากคุณต้องการขยายคำตอบเพื่อรวมรายละเอียดเกี่ยวกับวิธีที่ความไม่สามารถเปลี่ยนแปลงได้สามารถแก้ไขปัญหาการซิงโครไนซ์เธรดได้โปรดอย่าลังเล ประเด็นหลักที่ฉันตั้งใจจะแสดงให้เห็นก็คือมีหลายกรณีที่การสื่อสารแบบ async มีข้อได้เปรียบที่แตกต่างจากมัลติเธรด / กระบวนการและในทางกลับกัน
Evan Plaice

(ต่อ) แต่จริงๆแล้วถ้าฉันต้องการความสามารถในการประมวลผลที่มีขอบเขตมากของ CPU ฉันจะข้ามโมเดลนักแสดงและสร้างมันขึ้นมาเพื่อปรับขนาดไปยังโหนดเครือข่ายหลาย ๆ โหนด ทางออกที่ดีที่สุดที่ฉันเคยเห็นคือการใช้โมเดลงานของ 0MQ ผ่านการสื่อสารระดับซ็อกเก็ต ดูรูปที่ 5 @ zguide.zeromq.org/page:all
Evan Plaice

13

แนวทางแบบอะซิงโครนัสของ Microsoft เป็นสิ่งทดแทนที่ดีสำหรับวัตถุประสงค์ทั่วไปสำหรับการเขียนโปรแกรมแบบมัลติเธรด: ปรับปรุงการตอบสนองตามภารกิจ IO

อย่างไรก็ตามสิ่งสำคัญคือต้องตระหนักว่าวิธีการแบบอะซิงโครนัสนั้นไม่สามารถปรับปรุงประสิทธิภาพได้ทั้งหมดหรือปรับปรุงการตอบสนองสำหรับงานที่ต้องใช้ CPU มาก

มัลติเธรดสำหรับการตอบสนอง

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

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

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

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

ทางเลือก "แบบอะซิงโครนัส"

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

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

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

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

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

มัลติเธรดเพื่อประสิทธิภาพ

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

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

Parialism เล็กน้อย

แน่นอนว่าบางครั้งมันอาจเป็นเรื่องง่ายที่จะได้รับการเร่งความเร็วที่แท้จริงจากการมัลติเธรด

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

การใช้มัลติเธรดเพื่อประสิทธิภาพ

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

เช่นเดียวกับการเพิ่มประสิทธิภาพใด ๆ มักจะดีที่สุดในการปรับให้เหมาะสมหลังจากที่คุณได้ทำรายงานประสิทธิภาพของโปรแกรมของคุณและระบุฮอตสปอต: มันง่ายที่จะทำให้โปรแกรมช้าลงโดยการตัดสินใจโดยพลการว่าส่วนนี้ควรทำงานใน ก่อนอื่นให้พิจารณาว่าทั้งสองส่วนใช้เวลาส่วนสำคัญของ CPU หรือไม่

เธรดพิเศษหมายถึงค่าใช้จ่ายในการตั้งค่า / การฉีกขาดที่เพิ่มขึ้นและสวิตช์บริบทเพิ่มเติมหรือค่าใช้จ่ายการสื่อสารระหว่าง CPU มากขึ้น หากการทำงานไม่เพียงพอที่จะชดเชยค่าใช้จ่ายเหล่านั้นหากใช้ CPU แยกต่างหากและไม่จำเป็นต้องใช้เธรดแยกต่างหากสำหรับเหตุผลการตอบสนองมันจะทำให้สิ่งต่าง ๆ ช้าลงโดยไม่มีประโยชน์

ค้นหางานที่มีการพึ่งพาซึ่งกันและกันน้อยและนั่นเป็นการเพิ่มส่วนสำคัญของรันไทม์ของโปรแกรมของคุณ

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

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

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

อย่างไรก็ตามให้แน่ใจว่าได้ทำการโพรไฟล์เธรดและตรวจสอบให้แน่ใจว่าพวกเขาทำงานเพียงพอที่จะชดเชยค่าใช้จ่ายในบางจุด

อัลกอริทึมแบบขนาน

นอกจากนี้ยังมีปัญหามากมายที่สามารถเร่งความเร็วโดยใช้ตัวประมวลผลหลายตัว แต่มันก็ใหญ่เกินไปที่จะแยกระหว่างซีพียู

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

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


+1 สำหรับคำตอบที่เห็นได้ชัดเจน ฉันควรให้ความระมัดระวังในการรับคำแนะนำของ Microsoft ตามมูลค่าที่ตราไว้ โปรดทราบว่า. NET เป็นแพลตฟอร์มแบบซิงโครนัสแรกดังนั้นระบบนิเวศจึงมีความเอนเอียงเพื่อให้สิ่งอำนวยความสะดวก / เอกสารที่ดีขึ้นซึ่งสนับสนุนการสร้างโซลูชันแบบซิงโครนัส ตรงกันข้ามจะเป็นจริงสำหรับแพลตฟอร์ม async แรกเช่น Node.js
Evan Plaice

3

แอปพลิเคชันไม่ตอบสนองและเป็นเพียงช้าและไม่เป็นที่พอใจ

และมีปัญหาของคุณ UI แบบตอบสนองไม่ได้สร้างแอปพลิเคชันนักแสดง มักจะตรงกันข้าม หลายครั้งที่ใช้ตรวจสอบอินพุต UI แทนที่จะให้เธรดผู้ปฏิบัติงานทำงาน

เท่าที่ 'เพียง' มีวิธี async, ที่ multithreading เช่นกันแม้จะเอ็นดูสำหรับกรณีหนึ่งใช้เฉพาะที่อยู่ในสภาพแวดล้อมมากที่สุด ในคนอื่น ๆ นั้น async จะทำผ่าน coroutines ที่ ... ไม่พร้อมกันเสมอ

ตรงไปตรงมาฉันพบว่าการดำเนินการแบบ async นั้นยากกว่าที่จะให้เหตุผลและใช้ในวิธีที่ให้ประโยชน์จริง ๆ (ประสิทธิภาพความทนทานการบำรุงรักษา) แม้จะเปรียบเทียบกับวิธีการแบบแมนนวลมากกว่า ...


ทำไม ตัวอย่างเช่นสิ่งที่คุณพบกล้วยในห้องสมุดเพิ่มสัญญาณ 2?
user1849534
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.