ความแตกต่างระหว่าง coroutine และเธรดคืออะไร? มีข้อดีของการใช้อย่างใดอย่างหนึ่งมากกว่าอื่น ๆ ?
ความแตกต่างระหว่าง coroutine และเธรดคืออะไร? มีข้อดีของการใช้อย่างใดอย่างหนึ่งมากกว่าอื่น ๆ ?
คำตอบ:
ในขณะที่ Coroutines ดูเหมือนจะทำงานเหมือนกับเธรดในตอนแรกพวกเขาไม่ได้ใช้มัลติเธรดใด ๆ yield
พวกเขาจะดำเนินการตามลำดับจนกว่าพวกเขาจะ เครื่องยนต์จะตรวจสอบ coroutines ผลทั้งหมดเป็นส่วนหนึ่งของวงหลักของตัวเอง (ในสิ่งที่ชี้ว่าขึ้นอยู่กับชนิดของyield
, ตรวจสอบแผนภาพนี้สำหรับข้อมูลเพิ่มเติม ) ต่อพวกเขาหนึ่งหลังจากที่อื่นจนกว่าพวกเขาต่อไปyield
และจากนั้นดำเนินการกับวงหลัก
เทคนิคนี้มีข้อดีที่คุณสามารถใช้ coroutines โดยไม่ต้องปวดหัวที่เกิดจากปัญหากับมัลติเธรดจริง คุณจะไม่ได้รับการหยุดชะงักสภาพการแข่งขันหรือปัญหาประสิทธิภาพที่เกิดจากการสลับบริบทคุณจะสามารถแก้ไขข้อบกพร่องได้อย่างถูกต้องและคุณไม่จำเป็นต้องใช้คอนเทนเนอร์ข้อมูลที่ปลอดภัยสำหรับเธรด เนื่องจากเมื่อ Coroutine ถูกเรียกใช้งานเอ็นจิน Unity จะอยู่ในสถานะควบคุม มีความปลอดภัยในการใช้ฟังก์ชัน Unity ส่วนใหญ่
ในทางกลับกันคุณไม่มีความรู้อย่างแน่นอนเกี่ยวกับสถานะของลูปหลักของ Unity ในขณะนี้ (อันที่จริงแล้วอาจไม่ได้ทำงานเลย) ดังนั้นเธรดของคุณอาจทำให้เกิดความเสียหายค่อนข้างมากด้วยการทำบางอย่างในเวลาที่ไม่ควรทำสิ่งนั้น อย่าสัมผัสการทำงานใด ๆ สามัคคีพื้นเมืองจากย่อยหัวข้อ หากคุณต้องการสื่อสารระหว่าง sub-thread และ thread หลักของคุณให้ thread เขียนไปยัง container-object (!) thread-safe (!) และให้ MonoBehaviour อ่านข้อมูลนั้นในระหว่างฟังก์ชั่น Unity ปกติ
ข้อเสียของการไม่ทำมัลติเธรด "ของจริง" คือคุณไม่สามารถใช้ coroutines เพื่อคำนวณการคำนวณที่รุนแรงของ CPU กับคอร์ของ CPU หลาย ๆ ตัว อย่างไรก็ตามคุณสามารถใช้พวกเขาเพื่อแยกการคำนวณผ่านการอัปเดตหลายรายการ ดังนั้นแทนที่จะแช่แข็งเกมของคุณเป็นเวลาหนึ่งวินาทีคุณจะได้รับเฟรมเฉลี่ยต่ำกว่าหลายวินาที แต่ในกรณีนี้คุณต้องรับผิดชอบต่อyield
coroutine ทุกครั้งที่คุณต้องการอนุญาตให้ Unity ทำการอัพเดท
สรุป:
Coroutines คือสิ่งที่พวกเราในสาขาวิทยาศาสตร์คอมพิวเตอร์เรียกว่า "การทำงานหลายอย่างพร้อมกัน" พวกเขาเป็นวิธีการที่แตกต่างกันหลายกระแสของการดำเนินการเพื่อ interleave กับแต่ละอื่น ๆ อย่างร่วมมือ ในการทำงานแบบ multitasking สหกรณ์หนึ่งกระแสของการดำเนินการมีกรรมสิทธิ์ไม่มีปัญหา แต่เพียงผู้เดียวของ CPU yield
จนกว่าจะถึง ณ จุดนั้น Unity (หรือเฟรมเวิร์กที่คุณใช้) มีตัวเลือกเพื่อสลับไปยังการประมวลผลอื่น ๆ จากนั้นจะได้รับความเป็นเจ้าของ CPU ที่ไม่มีปัญหา แต่เพียงผู้เดียวจนกระทั่งyield
เป็น
หัวข้อคือสิ่งที่เราเรียกว่า "มัลติทาสกิ้งแบบยึดเอาเสียก่อน" เมื่อคุณใช้เธรดเฟรมเวิร์กขอสงวนสิทธิ์ในเวลาใดก็ได้เพื่อหยุดเธรดที่คุณคิดปานกลางและสลับไปใช้เธรดอื่น ไม่สำคัญว่าคุณจะอยู่ที่ไหน คุณสามารถหยุดบางส่วนได้ด้วยการเขียนตัวแปรไปยังหน่วยความจำในบางกรณี!
มีข้อดีและข้อเสียสำหรับแต่ละ ข้อเสียของ coroutines น่าจะง่ายที่สุดที่จะเข้าใจ ก่อนอื่น coroutines ทั้งหมดดำเนินการบนแกนเดียว หากคุณมีซีพียู quad core coroutines จะใช้หนึ่งในสี่คอร์เท่านั้น สิ่งนี้ลดความซับซ้อนของสิ่งต่าง ๆ แต่อาจเป็นปัญหาด้านประสิทธิภาพในบางกรณี นักโทษที่สองคือการที่คุณจะต้องทราบว่า coroutine yield
ใดสามารถหยุดโปรแกรมทั้งหมดของคุณเพียงโดยปฏิเสธที่จะ นี่เป็นปัญหาของ Mac OS9 เมื่อหลายปีก่อน OS9 รองรับการทำงานมัลติทาสกิ้งแบบร่วมมือเท่านั้นในคอมพิวเตอร์ทั้งหมด หากหนึ่งในโปรแกรมของคุณหยุดทำงานมันอาจหยุดคอมพิวเตอร์อย่างรุนแรงจนระบบปฏิบัติการไม่สามารถแสดงข้อความข้อผิดพลาดเพื่อแจ้งให้คุณทราบว่าเกิดอะไรขึ้น!
ข้อดีของ coroutines คือพวกเขาเข้าใจง่าย ข้อผิดพลาดที่คุณคาดเดาได้นั้นมีมากกว่า โดยทั่วไปแล้วพวกเขายังเรียกร้องให้มีทรัพยากรน้อยลงซึ่งจะมีประโยชน์เมื่อคุณปีนขึ้นไปสู่ 10 coronines หรือเธรดจำนวนมาก Candid Moon พูดถึงในความคิดเห็นที่ว่าถ้าคุณยังไม่ได้ศึกษาหัวข้ออย่างถูกต้องเพียงติดกับ coroutines และพวกเขาถูกต้อง Coroutines นั้นใช้งานง่ายกว่ามาก
หัวข้อเป็นสัตว์ที่แตกต่างกันอย่างสิ้นเชิง คุณต้องระวังความเป็นไปได้ที่เธรดอื่นอาจขัดจังหวะคุณตลอดเวลาและยุ่งกับข้อมูลของคุณ เธรดไลบรารีมีชุดเครื่องมือที่ทรงพลังทั้งหมดเพื่อช่วยคุณในเรื่องนี้เช่น mutexes และตัวแปรเงื่อนไขซึ่งช่วยให้คุณบอกระบบปฏิบัติการเมื่อมันปลอดภัยที่จะให้มันรันหนึ่งในเธรดอื่น ๆ ของคุณและเมื่อมันไม่ปลอดภัย มีหลักสูตรทั้งหมดที่ทุ่มเทให้กับการใช้เครื่องมือเหล่านี้ได้ดี หนึ่งในปัญหาที่มีชื่อเสียงที่เกิดขึ้นคือ "การหยุดชะงัก" ซึ่งเมื่อทั้งสองเธรดได้รับ "ติด" รอให้อีกฝ่ายหนึ่งปล่อยทรัพยากรบางอย่าง อีกปัญหาหนึ่งซึ่งสำคัญมากสำหรับ Unity คือไลบรารีจำนวนมาก (เช่น Unity) ไม่ได้ถูกออกแบบมาเพื่อรองรับการโทรจากหลายเธรด คุณสามารถทำลายกรอบงานของคุณได้อย่างง่ายดายหากคุณไม่สนใจว่าจะอนุญาตให้ใช้สายใดและสายใดถูกห้าม
เหตุผลสำหรับความซับซ้อนพิเศษนี้จริง ๆ แล้วง่ายมาก แบบจำลองมัลติทาสกิ้งแบบ preemptive นั้นคล้ายกับแบบจำลองแบบมัลติเธรดซึ่งอนุญาตให้คุณไม่เพียง แต่ขัดจังหวะเธรดอื่น ๆ แต่เพื่อรันเธรดแบบเคียงข้างกันบนแกนที่ต่างกัน นี่เป็นวิธีที่มีประสิทธิภาพอย่างไม่น่าเชื่อเป็นวิธีเดียวที่จะใช้ประโยชน์จากซีพียู quad core และ hex code ใหม่ที่กำลังจะออกมา แต่จะเปิดกล่อง pandoras ขึ้นมา กฎการซิงโครไนซ์สำหรับวิธีการจัดการข้อมูลนี้ในโลกแบบมัลติเธรดนั้นโหดร้ายทางบวก ในโลก C ++ มีบทความทั้งหมดที่อุทิศให้MEMORY_ORDER_CONSUME
ซึ่งเป็นมุมหนึ่ง itty-bitty-teeny-weenie ของการซิงโครไนซ์แบบมัลติเธรด
ข้อเสียของการทำเกลียว? ง่าย: มันยาก คุณสามารถเจอบั๊กทั้งหมดที่คุณไม่เคยเห็นมาก่อน หลายคนเรียกว่า "heisenbugs" ซึ่งบางครั้งจะปรากฏขึ้นและหายไปเมื่อคุณทำการดีบั๊ก เครื่องมือที่คุณได้รับเพื่อจัดการกับสิ่งเหล่านี้มีประสิทธิภาพมาก แต่ก็ยังอยู่ในระดับที่ต่ำมาก พวกเขาได้รับการออกแบบให้มีประสิทธิภาพในสถาปัตยกรรมของชิปที่ทันสมัยมากกว่าการออกแบบให้ใช้งานง่าย
อย่างไรก็ตามหากคุณต้องการใช้พลัง CPU ทั้งหมดนั่นเป็นเครื่องมือที่คุณต้องการ นอกจากนี้ยังมีเป็นจริงขั้นตอนวิธีการที่ง่ายต่อการเข้าใจใน multithreading กว่าที่พวกเขาอยู่กับ coroutines เพียงเพราะคุณปล่อยให้จับระบบปฏิบัติการทุกคำถามของการหยุดชะงักที่สามารถใช้สถานที่
ความคิดเห็นของ Candid Moon ที่ติดกับ coroutines เป็นคำแนะนำของฉันเช่นกัน หากคุณต้องการพลังของเธรดให้คอมมิต ออกไปและเรียนรู้หัวข้อจริงๆอย่างเป็นทางการ เรามีเวลาหลายสิบปีในการหาวิธีจัดระเบียบวิธีที่ดีที่สุดในการคิดเกี่ยวกับเธรดเพื่อให้คุณได้รับผลลัพธ์ที่น่าเชื่อถือได้อย่างปลอดภัยก่อนกำหนดและเพิ่มประสิทธิภาพตามที่คุณไป ตัวอย่างเช่นหลักสูตรที่มีสติทั้งหมดจะสอน mutexes ก่อนการสอนตัวแปรเงื่อนไข หลักสูตรมีเหตุผลทั้งหมดที่ครอบคลุม atomics จะสอน mutexes และตัวแปรเงื่อนไขอย่างสมบูรณ์ก่อนที่จะพูดถึงว่าอะตอมมีอยู่จริง (หมายเหตุ: ไม่มีสิ่งใดที่เป็นแบบฝึกหัดที่มีเหตุผลเกี่ยวกับอะตอมมิกส์) ลองเรียนรู้การทำเกลียวทีละน้อยและคุณขอร้องให้เป็นไมเกรน
join()
นี้ แต่คุณต้องการอะไรซักอย่าง หากคุณไม่มีสถาปนิกที่ออกแบบระบบเพื่อทำการซิงโครไนซ์สำหรับคุณคุณต้องเขียนด้วยตัวคุณเอง เป็นคนที่ไม่สิ่งมัลติเธรดผมหารูปแบบทางจิตของผู้คนที่ของวิธีการทำงานของเครื่องคอมพิวเตอร์จำเป็นต้องปรับก่อนที่พวกเขาจะทำข้อมูลให้ตรงกันได้อย่างปลอดภัย (ซึ่งเป็นสิ่งที่ดีหลักสูตรจะสอน)
join
ประสานและบรรลุประสิทธิภาพด้านบนโดยทั่วไปจะต้องมีอะไรที่ดีกว่า ประเด็นของฉันคือการใฝ่หาเศษเสี้ยวของผลประโยชน์ด้านประสิทธิภาพที่เป็นไปได้ของการทำเกลียวได้อย่างง่ายดายบางครั้งอาจดีกว่าการใช้วิธีการทำเกลียวที่ซับซ้อนกว่าเพื่อเก็บเกี่ยวเศษส่วนที่ใหญ่กว่า
ในเงื่อนไขที่ง่ายที่สุดที่เป็นไปได้ ...
หัวข้อ
เธรดไม่ได้ตัดสินใจว่าจะให้ผลผลิตเมื่อใดระบบปฏิบัติการ ('OS' เช่น Windows) จะตัดสินใจเมื่อมีการให้บริการชุดข้อความ ระบบปฏิบัติการเกือบทั้งหมดมีความรับผิดชอบสำหรับการจัดตารางเวลาเธรดมันตัดสินใจว่าเธรดที่จะเรียกใช้เมื่อใดที่จะเรียกใช้เธรดเหล่านี้และนานเท่าใด
นอกจากนี้เธรดอาจถูกเรียกใช้แบบซิงโครนัส (หนึ่งเธรดหลังจากที่อื่น) หรือแบบอะซิงโครนัส (เธรดต่าง ๆ ที่ทำงานบนแกน CPU ที่แตกต่างกัน) ความสามารถในการเรียกใช้แบบอะซิงโครนัสหมายความว่าเธรดสามารถทำงานได้มากขึ้นในระยะเวลาเดียวกัน (เนื่องจากเธรดกำลังทำสองสิ่งพร้อมกัน) แม้แต่เธรดแบบซิงโครนัสก็สามารถทำงานได้มากมายหากระบบปฏิบัติการดีในการกำหนดตารางเวลา
อย่างไรก็ตามพลังการประมวลผลพิเศษนี้มาพร้อมกับผลข้างเคียง ตัวอย่างเช่นถ้าสองเธรดพยายามเข้าถึงทรัพยากรเดียวกัน (เช่นรายการ) และแต่ละเธรดสามารถหยุดสุ่มที่จุดใดก็ได้ในรหัสการแก้ไขของเธรดที่สองอาจรบกวนการแก้ไขที่ทำโดยเธรดแรก (ดูเพิ่มเติมที่: เงื่อนไขการแข่งขันและการหยุดชะงัก )
หัวข้อนั้นยังถือว่าเป็น 'หนัก' เนื่องจากมีค่าใช้จ่ายจำนวนมากซึ่งหมายความว่ามีการปรับเวลาเป็นจำนวนมากเมื่อสลับเธรด
coroutines
ซึ่งแตกต่างจากหัวข้อ coroutines จะซิงโครนัสอย่างสมบูรณ์ coroutine เดียวเท่านั้นที่สามารถทำงานในเวลาใดก็ได้ นอกจากนี้ coroutines ยังสามารถเลือกได้ว่าจะให้ผลผลิตเมื่อใดและสามารถเลือกที่จะให้ผลผลิตที่จุดในรหัสที่มั่นใจ (เช่นในตอนท้ายของวงจรวนรอบ) นี่เป็นข้อได้เปรียบของปัญหาต่างๆเช่นสภาพการแข่งขันและการหยุดชะงักง่ายกว่ามากในการหลีกเลี่ยงและทำให้ Coroutines ร่วมมือกันได้ง่ายขึ้น
อย่างไรก็ตามนี่เป็นความรับผิดชอบที่สำคัญเช่นกันหาก coroutine ไม่สามารถให้ผลได้อย่างถูกต้องมันอาจใช้เวลาประมวลผลนานมาก
Coroutines โดยทั่วไปไม่จำเป็นต้องสลับบริบทและทำให้สลับเข้าและออกได้อย่างรวดเร็วและค่อนข้างเบา
สรุป:
เกลียว:
coroutine:
บทบาทของเธรดและ coroutines มีความคล้ายคลึงกันมาก แต่มีความแตกต่างกันในวิธีที่พวกเขาทำงานให้สำเร็จซึ่งหมายความว่าแต่ละคนมีความเหมาะสมกับงานที่แตกต่างกัน หัวข้อที่ดีที่สุดสำหรับงานที่พวกเขาสามารถมุ่งเน้นที่จะทำอะไรด้วยตัวเองโดยไม่ถูกขัดจังหวะจากนั้นส่งสัญญาณกลับเมื่อพวกเขาทำ Coroutines ดีที่สุดสำหรับงานที่สามารถทำได้ในขั้นตอนเล็ก ๆ และงานที่ต้องการการประมวลผลข้อมูลร่วมกัน