OpenMp: วิธีตรวจสอบให้แน่ใจว่าแต่ละเธรดทำงานซ้ำอย่างน้อย 1 ครั้งในการตั้งเวลาแบบไดนามิก

ฉันกำลังใช้การตั้งเวลาแบบไดนามิกสำหรับการวนซ้ำ แต่เมื่องานในแต่ละวนซ้ำน้อยเกินไป บางเธรดไม่ทำงานหรือเมื่อมีเธรดจำนวนมาก เช่น. มีการวนซ้ำ 100 ครั้งและมี 90 เธรด ฉันต้องการให้ทุกเธรดทำการวนซ้ำอย่างน้อยหนึ่งครั้ง และการวนซ้ำที่เหลือ 10 ครั้งสามารถกระจายไปยังเธรดที่ทำงานได้สำเร็จ ฉันจะทำเช่นนั้นได้อย่างไร?


person nanda    schedule 29.02.2020    source แหล่งที่มา


คำตอบ (1)


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

#pragma omp parallel for schedule(dynamic,1)
for(int i=0 ; i<100 ; ++i)
    compute(i);

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

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

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

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

อัปเดต

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

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

  • 8 เธรดแรกดำเนินการเป็นเวลา 100 มิลลิวินาที
  • 8 เธรดสุดท้ายจะดำเนินการเป็นเวลา 100 มิลลิวินาที
  • 8 เธรดแรกจะถูกดำเนินการอีกครั้งเป็นเวลา 100 มิลลิวินาที
  • 8 เธรดสุดท้ายจะถูกดำเนินการอีกครั้งเป็นเวลา 100 มิลลิวินาที
  • ฯลฯ

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

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

person Jérôme Richard    schedule 29.02.2020
comment
ฉันกำลังใช้แนวทางแรกและไม่ได้ผลอย่างที่คาดไว้ เธรดบางส่วนไม่ทำงาน ฉันตรวจสอบว่าอันไหนทำและผลลัพธ์ทำให้ฉันสับสน สำหรับเช่น เธรด 1,2,5,10,88 ใช้งานได้เท่านั้น หากผลลัพธ์คือเธรด 1,2,3,4,5 ใช้งานได้จาก 90 เธรดเท่านั้น ฉันสามารถสรุปได้ว่างานเสร็จสิ้นก่อนที่จะสร้างเธรดทั้งหมด และเป็นความจริงที่ว่าจำนวนเธรดที่มากขึ้นไม่ได้หมายความว่ารันไทม์เร็วขึ้น สิ่งที่ฉันต้องการคือการเปรียบเทียบขนาดเธรดความแตกต่างของรันไทม์ เช่น. รันโปรแกรมด้วย 1 เธรด รันโปรแกรมด้วย 2 เธรด.... มากถึง 100 เธรด (เท่าที่การวนซ้ำมี) เพื่อที่ผมจะสามารถเปรียบเทียบรันไทม์ได้ - person nanda; 29.02.2020
comment
ผลลัพธ์ของ std::thread::hardware_concurrency() บนเครื่องของคุณคืออะไร? - person Jérôme Richard; 29.02.2020
comment
เมื่อฉันวิ่งมันคือ 8 - person nanda; 01.03.2020
comment
ฉันพบว่าหากฉันใส่หมายเลขเธรดมากกว่า 8 จะมีเพียง 8 เธรดเท่านั้นที่ทำงานได้ทั้งในการตั้งเวลาแบบไดนามิกและแบบมีไกด์ อย่างไรก็ตาม ในการจัดกำหนดการแบบคงที่ เธรดทั้งหมดทำงานได้ มันเกิดขึ้นได้อย่างไร? - person nanda; 01.03.2020
comment
คำตอบได้รับการอัปเดตเพื่อคำนึงถึงข้อมูลนี้ - person Jérôme Richard; 01.03.2020