เหตุใดการใช้เธรดมากกว่าทำให้ช้ากว่าการใช้เธรดที่น้อยกว่า


29

พยายามที่จะเรียกใช้โปรแกรม X ใช้8 เธรดและมันถูกกว่าในn นาที
พยายามที่จะเรียกใช้โปรแกรมเดียวกันโดยใช้50 หัวข้อและมันถูกกว่าในn * 10 นาที

เหตุใดสิ่งนี้จึงเกิดขึ้นและฉันจะได้รับจำนวนเธรดที่ดีที่สุดที่ฉันสามารถใช้ได้อย่างไร

คำตอบ:


33

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

เป็นกระบวนการ / เธรด

  • CPU ถูกผูกไว้ (ต้องการทรัพยากรของ CPU จำนวนมาก)
  • หน่วยความจำถูกผูกไว้ (ต้องการทรัพยากร RAM จำนวนมาก)
  • I / O ถูกผูกไว้ (เครือข่ายและ / หรือทรัพยากรฮาร์ดไดรฟ์)

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

คุณสามารถใช้ntopและiostatและvmstatเพื่อวินิจฉัยสิ่งที่เกิดขึ้น


8
ฮาร์ดแวร์ก็มีความสำคัญเช่นกัน แบบ
ฟิสิคัล

45

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

หากคุณมี 1-3 คนคุณจะพลาดที่จะใช้พื้นที่ทางเดิน หากคุณมี 5 คนขึ้นไปอย่างน้อยหนึ่งคนเหล่านั้นจะติดคิวหลังคนอื่นตลอดเวลา การเพิ่มคนมากขึ้นเรื่อย ๆ เพียงอุดตันทางเดินมันไม่ได้เพิ่มความรวดเร็ว

ดังนั้นคุณต้องการมีคนจำนวนมากเท่าที่คุณสามารถพอดีโดยไม่ทำให้เกิดการเข้าคิวใด ๆ ทำไมคุณมีการเข้าคิว (หรือคอขวด) ขึ้นอยู่กับคำถามในคำตอบของ slm


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

7
ตัวอย่างที่ดี +1 Bakuriu เป็นตัวอย่างที่แสดงให้เห็นถึงปัญหาของทรัพยากรที่ใช้ร่วมกันที่ จำกัด มันอธิบายปัญหาไม่ใช่วิธีหาจำนวนเธรดที่เหมาะสมที่สุด
Bananguin

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

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

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

20

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

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


นี่ควรเป็นคำตอบทั่วไปที่ระบุจำนวนข้อมูลที่มีอยู่ เราไม่ต้องการวิทยานิพนธ์และปรัชญาที่เต็มเปี่ยมเหมือนคำตอบอื่น ๆ
Allahjane

8

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

แต่การโยนในหัวข้อเพิ่มเติมอย่างชัดเจนสามารถทำให้สิ่งเลวร้ายลง

ในสาขาการคำนวณแบบขนานมีกฎหมายของ Amdahlที่สามารถใช้งานได้ (หรือไม่สามารถไม่ได้ แต่คุณไม่ได้อธิบายรายละเอียดของปัญหาของคุณดังนั้น .... ) และสามารถให้ข้อมูลเชิงลึกทั่วไปเกี่ยวกับปัญหาในระดับนี้

ประเด็นของกฎหมายของ Amdahl ก็คือว่าในโปรแกรมใด ๆ (ในอัลกอริทึมใด ๆ ) จะมีเปอร์เซ็นต์ที่ไม่สามารถทำงานแบบขนานได้ ( ส่วนต่อเนื่อง ) และมีอีกเปอร์เซ็นต์ที่สามารถทำงานแบบขนาน ( ส่วนขนาน ) ได้อย่างชัดเจน สองส่วนนี้รวมกันได้มากถึง 100%]

ส่วนนี้สามารถแสดงเป็นเปอร์เซ็นต์ของเวลาดำเนินการ ตัวอย่างเช่นอาจมี 25% ของเวลาที่ใช้ในการดำเนินการตามลำดับอย่างเคร่งครัดและ 75% ของเวลาที่เหลือจะใช้ในการดำเนินการที่สามารถดำเนินการแบบขนาน

ภาพจาก Wikipedia (ภาพจากWikipedia )

กฎหมายของ Amdahl ทำนายว่าสำหรับทุก ๆ ส่วนที่ขนานกัน (เช่น 75%) ของโปรแกรมคุณสามารถเพิ่มความเร็วในการประมวลผลได้เพียงเท่านี้ (เช่นมากที่สุด 4 เท่า) แม้ว่าคุณจะใช้โปรเซสเซอร์มากขึ้นเรื่อย ๆ ในการทำงาน

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

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

การทำนายแบบเชิงประจักษ์ (ประมาณ CPU ครั้ง) ไม่ได้พิจารณาถึงคอขวดที่ใช้งานได้อื่น ๆ เช่น

  1. จำกัด I / O ความเร็ว (ฮาร์ดดิสก์และเครือข่าย "ความเร็ว")
  2. จำกัด ขนาดหน่วยความจำ
  3. คนอื่น ๆ

ที่สามารถเป็นปัจจัย จำกัด ในการใช้งานจริง


ต้องเลือกคำตอบนี้
Eonil

6

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

ในกรณีของคุณเมื่อมีเธรด 50 เธรดการสลับบริบทจะเกิดขึ้นมากมายเมื่อเปรียบเทียบกับการรันเพียง 10 เธรด

ค่าใช้จ่ายในครั้งนี้ได้รับการแนะนำเนื่องจากการสลับบริบทเป็นสิ่งที่ทำให้โปรแกรมของคุณทำงานช้า


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

การสลับบริบทของเธรดในและของตัวเองยกเว้นว่าเรากำลังเผชิญกับการสลับบริบทจำนวนมากเป็นไปได้ว่าจะไม่มีผลกระทบต่อประสิทธิภาพการทำงานตามลำดับ 50 เธรดนั้นสูง แต่ไม่สุดขีด (ในกล่องของฉันตอนนี้ps ax | wc -lรายงาน 225 กระบวนการและมันไม่โหลดหนักมาก) ฉันอยากจะไปกับการเดา @ EightBitTony; แคชโมฆะน่าจะเป็นปัญหาที่ใหญ่กว่าเพราะทุกครั้งที่คุณล้างแคชของ CPU มีการรอมหายุครหัสและข้อมูลจาก RAM
CVn

2

ในการแก้ไขคำอุปมาของ EightBitTony:

"ทำไมสิ่งนี้ถึงเกิดขึ้นได้?" เป็นคำตอบที่ง่าย ลองนึกภาพคุณมีสระว่ายน้ำสองสระสระหนึ่งสระเต็มและสระว่าง คุณต้องการที่จะย้ายน้ำทั้งหมดจากที่หนึ่งไปยังที่อื่น ๆ และมี 4 บุ้งกี๋ จำนวนคนที่มีประสิทธิภาพมากที่สุดคือ 4

หากคุณมี 1-3 คนคุณก็พลาดที่จะใช้ที่เก็บบางอัน ถ้าคุณมี 5 คนหรือมากกว่านั้นอย่างน้อยหนึ่งในคนเหล่านั้นจะติดอยู่รอถัง กำลังเพิ่มผู้คนมากขึ้น ... ไม่ได้เพิ่มความเร็วในกิจกรรม

ดังนั้นคุณจึงต้องการที่จะมีเป็นคนจำนวนมากที่สุดเท่าที่สามารถทำงานบางอย่าง (ใช้ถัง) ไปพร้อม ๆ กัน

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

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

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

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


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

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


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

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

0

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

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