การล็อก mutex ที่ปลดล็อกมีประสิทธิภาพเพียงใด Mutex มีราคาเท่าใด


149

ในภาษาระดับต่ำ (C, C ++ หรืออะไรก็ตาม): ฉันมีตัวเลือกระหว่างการมี mutexes หลายอัน (เช่น pthread ให้ฉันหรืออะไรก็ตามที่ไลบรารี่ของระบบดั้งเดิมจัดหาให้) หรืออันเดียวสำหรับวัตถุ

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

Mutex มีค่าใช้จ่ายเท่าไหร่ เป็นปัญหาหรือไม่ที่จะมีmutex จำนวนมากจริงๆ หรือฉันสามารถโยนตัวแปร mutex ให้มากที่สุดเท่าที่ฉันมีได้ในintตัวแปรและมันก็ไม่สำคัญอะไร

(ฉันไม่แน่ใจว่าความแตกต่างระหว่างฮาร์ดแวร์ต่างกันมากแค่ไหนถ้ามีฉันอยากรู้เกี่ยวกับมันด้วย แต่ส่วนใหญ่ฉันสนใจฮาร์ดแวร์ทั่วไป)

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


การโพสต์บล็อกของ WebKits (2016) เกี่ยวกับการล็อคนั้นเกี่ยวข้องกับคำถามนี้มากและอธิบายความแตกต่างระหว่าง spinlock, ล็อคปรับตัว, futex และอื่น ๆ


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

2
@Gian: แน่นอนฉันหมายถึงคำถามย่อยนี้ในคำถามของฉัน ฉันต้องการทราบเกี่ยวกับฮาร์ดแวร์ทั่วไป แต่ก็มีข้อยกเว้นที่น่าสังเกตว่ามีหรือไม่
อัลเบิร์ต

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

15
@Gian: แล้วโปรดให้คำตอบนี้อย่างแน่นอน กรุณาบอกว่ามันคืออะไรใน x86 และ amd64 โปรดยกตัวอย่างสำหรับสถาปัตยกรรมที่มี 1 คำสั่งและให้หนึ่งที่เป็น 10k ไม่ชัดเจนว่าฉันต้องการทราบจากคำถามของฉันหรือไม่
อัลเบิร์ต

คำตอบ:


120

ฉันมีตัวเลือกระหว่างมีทั้ง mutexes หรืออันเดียวสำหรับวัตถุ

หากคุณมีหลายเธรดและการเข้าถึงวัตถุเกิดขึ้นบ่อยครั้งการล็อคหลายครั้งจะเพิ่มความขนาน ค่าใช้จ่ายในการบำรุงรักษาเนื่องจากการล็อกมากกว่าหมายถึงการดีบั๊กของการล็อกมากขึ้น

มันมีประสิทธิภาพแค่ไหนในการล็อค mutex? เช่นมีคำแนะนำของแอสเซมเบลอร์เท่าใดและมีเวลาเท่าไร (ในกรณีที่ Mutex ปลดล็อค)

คำสั่งแอสเซมเบลอร์ที่แม่นยำนั้นมีค่าใช้จ่ายน้อยที่สุดของmutex - การรับประกันความสอดคล้องกันของหน่วยความจำ / แคชเป็นค่าใช้จ่ายหลัก และบ่อยครั้งที่มีการล็อคโดยเฉพาะน้อยกว่า - ดีกว่า

Mutex ทำจากสองส่วนหลัก (การปรับขนาดใหญ่เกินไป): (1) การตั้งค่าสถานะเพื่อระบุว่า Mutex ถูกล็อคหรือไม่และ (2) รอคิว

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

การล็อค mutex ที่ปลดล็อคนั้นราคาถูกจริงๆ การปลดล็อกการช่วงชิง mutex โดยไม่ต้องมีราคาถูกเกินไป

Mutex มีค่าใช้จ่ายเท่าไหร่ เป็นปัญหาหรือไม่ที่จะมี mutex จำนวนมากจริงๆ หรือฉันจะเพียงแค่โยนตัวแปร mutex ให้มากที่สุดเท่าที่ฉันมีตัวแปร int และมันไม่สำคัญหรอก

คุณสามารถโยนตัวแปร mutex ลงในรหัสของคุณได้มากเท่าที่คุณต้องการ คุณถูก จำกัด ด้วยจำนวนหน่วยความจำที่แอปพลิเคชันของคุณสามารถจัดสรรได้

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

  1. ล็อคน้อยลงหมายถึงการต่อสู้มากขึ้น (syscalls ช้าแผงขายของ CPU) และการขนานที่น้อยกว่า
  2. ล็อคน้อยลงหมายถึงปัญหาน้อยกว่าการดีบักปัญหามัลติเธรด
  3. การล็อคมากขึ้นหมายถึงการทะเลาะวิวาทน้อยลงและความเท่าเทียมที่สูงขึ้น
  4. การล็อคมากขึ้นหมายถึงโอกาสที่จะได้รับการหยุดชะงักที่ไม่สามารถเอาชนะได้มากขึ้น

รูปแบบการล็อคที่สมดุลสำหรับแอพพลิเคชั่นควรจะได้รับการดูแลและบำรุงรักษาโดยทั่วไปแล้วจะทำให้สมดุล # 2 และ # 3 สมดุลกัน


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

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

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


ขอบคุณที่ตอบคำถามของฉันเป็นส่วนใหญ่ ฉันไม่ทราบว่าเคอร์เนล (เช่นเคอร์เนล Linux) จัดการ mutexes และคุณควบคุมผ่าน syscalls แต่ในขณะที่ Linux จัดการการตั้งเวลาและการสลับบริบทสิ่งนี้สมเหตุสมผล แต่ตอนนี้ฉันมีจินตนาการคร่าวๆเกี่ยวกับสิ่งที่การล็อก / ปลดล็อก mutex จะทำภายใน
อัลเบิร์ต

2
@Albert: โอ้ ฉันลืมสวิทช์บริบท ... สวิทช์บริบทจะระบายประสิทธิภาพเกินไป ถ้าการล็อกการล็อกล้มเหลวและเธรดต้องรอนั่นเป็นครึ่งหนึ่งของการสลับบริบท CS นั้นเร็ว แต่เนื่องจาก CPU อาจถูกใช้โดยกระบวนการอื่นบางแคชจะถูกเติมด้วยข้อมูลเอเลี่ยน ในที่สุดหลังจากที่เธรดได้ล็อกแล้วโอกาสที่จะเกิดขึ้นกับซีพียูจะต้องโหลดใหม่ทุกอย่างจาก RAM อีกครั้ง
Dummy00001

@ Dummy00001 การสลับไปยังกระบวนการอื่นหมายความว่าคุณต้องเปลี่ยนการแมปหน่วยความจำของ CPU นั่นไม่ถูกเลย
curiousguy

27

ฉันอยากรู้สิ่งเดียวกันดังนั้นฉันจึงวัดมัน ในกล่องของฉัน (AMD FX (tm) -8150 โปรเซสเซอร์แปดคอร์ที่ 3.612361 GHz) การล็อคและปลดล็อก mutex ที่ปลดล็อคที่อยู่ในสายแคชของตัวเองและแคชไว้แล้วใช้เวลา 47 นาฬิกา (13 ns)

เนื่องจากการซิงโครไนซ์ระหว่างสองคอร์ (ฉันใช้ CPU # 0 และ # 1) ฉันสามารถโทรล็อค / ปลดล็อคคู่ได้เพียงครั้งเดียวทุกๆ 102 ns ในสองเธรดดังนั้นทุกๆ 51 ns ซึ่งหนึ่งสามารถสรุปได้ว่าใช้เวลาประมาณ 38 ns เพื่อกู้คืนหลังจากเธรดปลดล็อกก่อนที่เธรดถัดไปจะสามารถล็อกได้อีกครั้ง

โปรแกรมที่ฉันใช้ตรวจสอบสิ่งนี้สามารถพบได้ที่นี่: https://github.com/CarloWood/ai-statefultask-testsuite/blob/b69b112e2e91d35b56a39f41809d3e3de2f9e4b8/src/mutex_test.cxx

โปรดทราบว่ามันมีค่าฮาร์ดโค้ดที่เฉพาะเจาะจงสำหรับกล่องของฉัน (ค่า Xrange, Yrange และ rdtsc) ดังนั้นคุณอาจต้องทดลองกับมันก่อนที่มันจะทำงานให้คุณ

กราฟที่สร้างในสถานะนั้นคือ:

ป้อนคำอธิบายรูปภาพที่นี่

สิ่งนี้แสดงผลลัพธ์ของการวัดประสิทธิภาพบนโค้ดต่อไปนี้:

uint64_t do_Ndec(int thread, int loop_count)
{
  uint64_t start;
  uint64_t end;
  int __d0;

  asm volatile ("rdtsc\n\tshl $32, %%rdx\n\tor %%rdx, %0" : "=a" (start) : : "%rdx");
  mutex.lock();
  mutex.unlock();
  asm volatile ("rdtsc\n\tshl $32, %%rdx\n\tor %%rdx, %0" : "=a" (end) : : "%rdx");
  asm volatile ("\n1:\n\tdecl %%ecx\n\tjnz 1b" : "=c" (__d0) : "c" (loop_count - thread) : "cc");
  return end - start;
}

การเรียก rdtsc สองครั้งจะวัดจำนวนนาฬิกาที่ใช้ในการล็อคและปลดล็อค `mutex '(ด้วยโอเวอร์เฮดของ 39 นาฬิกาสำหรับการโทร rdtsc บนกล่องของฉัน) asm ที่สามคือการวนรอบหน่วงเวลา ขนาดของการวนรอบหน่วงเวลามีขนาดเล็กกว่า 1 สำหรับเธรด 1 มากกว่าสำหรับเธรด 0 ดังนั้นเธรด 1 จะเร็วกว่าเล็กน้อย

ฟังก์ชั่นดังกล่าวเรียกว่าในวง จำกัด ขนาด 100,000 แม้ว่าฟังก์ชั่นจะเร็วกว่าเล็กน้อยสำหรับเธรด 1 ทั้งสองลูปซิงโครไนซ์เนื่องจากการเรียกไปยัง mutex สิ่งนี้สามารถมองเห็นได้ในกราฟจากข้อเท็จจริงที่ว่าจำนวนนาฬิกาที่วัดได้สำหรับคู่ล็อค / ปลดล็อกนั้นมีขนาดใหญ่กว่าสำหรับเธรด 1 เล็กน้อยเพื่อพิจารณาความล่าช้าที่สั้นลงในลูปด้านล่าง

ในกราฟด้านบนจุดด้านล่างขวาคือการวัดที่มีความล่าช้า loop_count 150 จากนั้นติดตามจุดที่ด้านล่างไปทางซ้ายวน loop_count จะลดลงหนึ่งการวัดแต่ละครั้ง เมื่อกลายเป็น 77 ฟังก์ชันจะถูกเรียกทุก ๆ 102 ns ในทั้งสองเธรด หากภายหลัง loop_count ถูกลดลงยิ่งไปกว่านั้นมันเป็นไปไม่ได้ที่จะซิงโครไนซ์เธรดและ mutex เริ่มถูกล็อคจริงเกือบตลอดเวลาทำให้เกิดการเพิ่มจำนวนของนาฬิกาที่ใช้ในการล็อค / ปลดล็อก นอกจากนี้เวลาเฉลี่ยของการเรียกใช้ฟังก์ชันเพิ่มขึ้นเนื่องจากสิ่งนี้ ดังนั้นพล็อตจะชี้ขึ้นและไปทางขวาอีกครั้ง

จากนี้เราสามารถสรุปได้ว่าการล็อกและปลดล็อก mutex ทุก ๆ 50 ns ไม่ใช่ปัญหาในกล่องของฉัน

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

พยายามล็อก mutexes ให้สั้นที่สุด เหตุผลเดียวที่จะทำให้พวกเขา - พูด - นอกวงจะเป็นว่าถ้าวนรอบเร็วกว่าทุก ๆ 100 ns (หรือมากกว่าจำนวนกระทู้ที่ต้องการเรียกใช้วนรอบนั้นในเวลาเดียวกัน 50 ns) หรือเมื่อ 13 ns ครั้ง ขนาดลูปจะล่าช้ากว่าความล่าช้าที่คุณได้รับจากการช่วงชิง

แก้ไข: ฉันมีความรู้มากขึ้นเกี่ยวกับเรื่องนี้และเริ่มสงสัยข้อสรุปที่ฉันนำเสนอที่นี่ ก่อนอื่น CPU 0 และ 1 กลายเป็นไฮเปอร์เธรด แม้ว่าเอเอ็มดีอ้างว่ามี 8 คอร์จริง แต่ก็มีบางอย่างที่น่าจับตามองเพราะความล่าช้าระหว่างคอร์สองคอร์นั้นใหญ่กว่ามาก (เช่น 0 และ 1 ในรูปแบบคู่เช่นเดียวกับ 2 และ 3, 4 และ 5 และ 6 และ 7 ) ประการที่สอง std :: mutex ถูกนำไปใช้ในทางที่มันหมุนล็อคบิตก่อนที่จะทำการเรียกระบบเมื่อมันล้มเหลวในการรับล็อคทันทีบน mutex (ซึ่งไม่ต้องสงสัยเลยว่าช้ามาก) ดังนั้นสิ่งที่ฉันวัดได้ที่นี่คือซิตตัสที่สมบูรณ์แบบที่สุดและในการฝึกการล็อคและปลดล็อคอาจใช้เวลามากขึ้นต่อการล็อค / ปลดล็อก

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


10

ขึ้นอยู่กับสิ่งที่คุณเรียกว่า "mutex" โหมด OS และอื่น ๆ

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

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

ตัวอย่างเช่นในโปรเซสเซอร์ Intel Core Duo, Windows XP การทำงานแบบ Interlocked: ใช้เวลาประมาณ 40 รอบ CPU การเรียกใช้โหมดเคอร์เนล (เช่นการเรียกใช้ระบบ) - ประมาณ 2000 รอบ CPU

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


7
ส่วนที่สำคัญของ Windows อยู่ใกล้กับ mutexes มาก พวกเขามีความหมาย mutex ปกติ แต่พวกเขาเป็นกระบวนการท้องถิ่น ส่วนสุดท้ายทำให้เร็วขึ้นมากเนื่องจากสามารถจัดการทั้งหมดในกระบวนการของคุณ (และทำให้รหัสโหมดผู้ใช้)
MSalters

2
จำนวนจะมีประโยชน์มากขึ้นถ้าจำนวนรอบ CPU ของการดำเนินงานทั่วไป (เช่นเลขคณิต / if-else / cache-miss / อ้อม) จัดให้มีการเปรียบเทียบ .... มันจะยิ่งดีถ้ามีการอ้างอิงของตัวเลข ในอินเทอร์เน็ตมันยากมากที่จะหาข้อมูลดังกล่าว
javaLover

@javaLover Operations ไม่ทำงานในรอบ มันรันบนหน่วยเลขคณิตเป็นจำนวนรอบ มันแตกต่างกันมาก ค่าใช้จ่ายของการเรียนการสอนใด ๆ ในเวลาไม่ได้เป็นปริมาณที่กำหนดไว้เฉพาะค่าใช้จ่ายในการใช้ทรัพยากร แบ่งปันทรัพยากรเหล่านี้ ผลกระทบของคำแนะนำหน่วยความจำขึ้นอยู่จำนวนมากแคช ฯลฯ
curiousguy

@curtguy เห็นด้วย ฉันไม่ชัดเจน ฉันต้องการคำตอบเช่นstd::mutexระยะเวลาการใช้งานเฉลี่ย (ในวินาที) 10 int++ครั้งกว่า อย่างไรก็ตามฉันรู้ว่ามันยากที่จะตอบเพราะมันขึ้นอยู่กับหลายสิ่งหลายอย่าง
javaLover

6

ค่าใช้จ่ายจะแตกต่างกันไปขึ้นอยู่กับการใช้งาน แต่คุณควรคำนึงถึงสองสิ่ง:

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

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

ในทั้งสองกรณีคำแนะนำนั้นค่อนข้างมีประสิทธิภาพ

เกี่ยวกับว่าคุณควรจัดเตรียม mutex เดียวสำหรับโครงสร้างข้อมูลขนาดใหญ่หรือมี mutex จำนวนมากหนึ่งอันสำหรับแต่ละส่วนของมันนั่นคือการกระทำที่สมดุล

ด้วยการมี mutex เพียงครั้งเดียวคุณจะมีความเสี่ยงสูงกว่าในการโต้แย้งระหว่างหลายเธรด คุณสามารถลดความเสี่ยงนี้โดยให้มี mutex ต่อส่วน แต่คุณไม่ต้องการรับสถานการณ์ที่เธรดต้องล็อก 180 mutexes เพื่อทำงาน :-)


1
ใช่ แต่มีประสิทธิภาพแค่ไหน ? มันเป็นคำสั่งเครื่องเดียวหรือไม่? หรือประมาณ 10 หรือประมาณ 100 1000? มากกว่า? ทั้งหมดนี้ยังคงมีประสิทธิภาพ แต่สามารถสร้างความแตกต่างในสถานการณ์ที่รุนแรง
อัลเบิร์ต

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

การทดสอบและตั้งค่าบัสที่ล็อกไว้เป็นคำสั่งเดียว (ค่อนข้างยาว) ใน x86 ส่วนที่เหลือของเครื่องจักรที่ใช้มันค่อนข้างเร็ว (“ การทดสอบสำเร็จหรือไม่?” เป็นคำถามที่ CPU ทำงานเร็ว) แต่มันเป็นความยาวของคำสั่งล็อคบัสที่สำคัญจริงๆเพราะเป็นส่วนที่บล็อกสิ่งต่าง ๆ โซลูชั่นที่มีการอินเตอร์รัปต์นั้นช้ากว่ามากเพราะการจัดการพวกมันนั้นถูก จำกัด ไว้ที่เคอร์เนลระบบปฏิบัติการเพื่อหยุดการโจมตี DoS เล็กน้อย
Donal Fellows

BTW อย่าใช้ drop / reacquire เป็นวิธีการที่จะให้ผลตอบแทนกับผู้อื่น นั่นเป็นกลยุทธ์ที่ดูดระบบมัลติคอร์ (เป็นหนึ่งในสิ่งที่ค่อนข้างน้อยที่ CPython ผิด)
Donal Fellows

@ Donal: คุณหมายถึงอะไรจากการดร็อป / reququire? นั่นฟังดูสำคัญ คุณให้ข้อมูลเพิ่มเติมกับฉันได้ไหม
อัลเบิร์ต

5

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

y = exp(-j*0.0001);
pthread_mutex_lock(&lock);
x += y ;
pthread_mutex_unlock(&lock);

ด้วยหนึ่งเธรดโปรแกรมจะสรุปผล 10,000,000 ค่าทันที (น้อยกว่าหนึ่งวินาที) ด้วยสองเธรด (บน MacBook ที่มี 4 คอร์) โปรแกรมเดียวกันใช้เวลา 39 วินาที

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