อัลกอริทึมแบบขนาน (GPU) สำหรับออโตเซลลูมิเนียมแบบอะซิงโครนัส


12

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

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

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

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

  1. เลือกคู่ของเซลล์ที่อยู่ใกล้เคียงโดยการสุ่ม

  2. คำนวณฟังก์ชัน "พลังงาน"ตามพื้นที่ใกล้เคียงรอบ ๆ เซลล์เหล่านี้ΔE

  3. ด้วยความน่าจะเป็นที่ขึ้นอยู่กับ (ด้วยพารามิเตอร์ a) ไม่ว่าจะสลับสถานะของเซลล์ทั้งสองหรือไม่ทำอะไรเลย βeβΔEβ

  4. ทำซ้ำขั้นตอนข้างต้นอย่างไม่มีกำหนด

นอกจากนี้ยังมีภาวะแทรกซ้อนบางอย่างที่เกี่ยวข้องกับเงื่อนไขขอบเขต แต่ฉันคิดว่าสิ่งเหล่านี้จะไม่เกิดความยุ่งยากในการขนานกัน

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

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

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

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

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

คำถามเฉพาะของฉันมีดังนี้:

  • มีอัลกอริทึมใด ๆ ข้างต้นเป็นวิธีที่สมเหตุสมผลในการเข้าหา GPU แบบขนานของโมเดล CA แบบอะซิงโครนัสไหม

  • มีวิธีที่ดีกว่า?

  • มีรหัสห้องสมุดสำหรับปัญหาประเภทนี้หรือไม่

  • ฉันจะหาคำอธิบายภาษาอังกฤษที่ชัดเจนของวิธีการ "บล็อกซิงโครนัส" ได้อย่างไร

ความคืบหน้า

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

แนวคิดคือการแทนที่ asynchronous CA (จากนี้ไป ACA) ด้วย stochastic synchronous CA (SCA) ที่ทำงานอย่างเท่าเทียมกัน เมื่อต้องการทำสิ่งนี้เราต้องจินตนาการว่า ACA เป็นกระบวนการปัวซอง นั่นคือเวลาดำเนินการอย่างต่อเนื่องและแต่ละเซลล์เป็นความน่าจะเป็นคงที่ต่อหนึ่งหน่วยเวลาในการดำเนินการฟังก์ชั่นการอัพเดทโดยไม่ขึ้นกับเซลล์อื่น

เราสร้าง SCA ที่แต่ละเซลล์เก็บสองสิ่ง: สถานะ ของเซลล์ (เช่นข้อมูลที่จะถูกเก็บไว้ในแต่ละเซลล์ในการดำเนินการตามลำดับ) และหมายเลขจุดลอยตัวแทน (ต่อเนื่อง ) เวลาที่จะอัปเดตครั้งต่อไป เวลาต่อเนื่องนี้ไม่สอดคล้องกับขั้นตอนการอัพเดตของ SCA ฉันจะอ้างถึงหลังว่า "เวลาตรรกะ" ค่าเวลา initialised สุ่มตามการกระจายชี้แจง:แลมบ์ดา) (โดยที่เป็นพารามิเตอร์ที่สามารถเลือกค่าได้ตามใจชอบ)ทีฉันเจทีฉันJ ( 0 ) ~ ประสบการณ์( λ ) λXijtijtij(0)Exp(λ)λ

ในแต่ละขั้นตอนเวลาแบบลอจิคัลเซลล์ของ SCA จะถูกอัพเดตดังนี้:

  • ถ้าใด ๆในเขตของเวลาไม่ทำอะไรเลยฉัน, j t k l < t ฉันjk,li,jtkl<tij

  • มิฉะนั้น (1) อัปเดตสถานะตามสถานะของเซลล์ข้างเคียงโดยใช้กฎเดียวกับ ACA ดั้งเดิม และ (2) สร้างค่าสุ่มและปรับปรุงเพื่อT X k L Δ T ~ ประสบการณ์( λ ) เสื้อฉันเจทีฉันเจ + Δ ทีXijXklΔtExp(λ)tijtij+Δt

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

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


บางทีคุณสามารถกำหนดปัญหาของคุณด้วยวิธี stencil-based มีซอฟต์แวร์จำนวนมากสำหรับปัญหาที่มีลายฉลุ คุณอาจดูได้ที่: libgeodecomp.org/gallery.htmlเกมแห่งชีวิตของ Conway สิ่งนี้อาจมีความคล้ายคลึงกันบ้าง
vanCompute

@vanCompute ที่ดูเหมือนว่าเป็นเครื่องมือที่ยอดเยี่ยม แต่จากการสืบสวนครั้งแรกของฉัน (ค่อนข้างคร่าวๆ) ดูเหมือนว่ากระบวนทัศน์รหัส stencil เป็นแบบซิงโครนัสโดยเนื้อแท้ดังนั้นจึงอาจไม่เหมาะกับสิ่งที่ฉันพยายามทำ ฉันจะตรวจสอบมันต่อไปอย่างไรก็ตาม
นาธาเนียล

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

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

ตกลงและคุณกำหนดการทับซ้อนระหว่างเพื่อจับคู่การอัพเดตอย่างไร หากคู่ตัวเองทับซ้อนกันหรือถ้าเพื่อนบ้านของพวกเขาทับซ้อนกัน?
เปโดร

คำตอบ:


4

ฉันจะใช้ตัวเลือกแรกและจะใช้การเรียกใช้ AC แบบซิงโครนัสมาก่อน (ใช้ GPU) เพื่อตรวจหาการชนดำเนินขั้นตอนของ AC หกเหลี่ยมซึ่งกฎคือค่าของเซลล์กลาง = Sum (เพื่อนบ้าน) CA นี้ต้องมี ควรเริ่มต้นเจ็ดสถานะด้วยเซลล์ที่เลือกแบบสุ่มและตรวจสอบสถานะก่อนที่จะเรียกใช้กฎการอัปเดตสำหรับแต่ละ GPU

ตัวอย่าง 1. ค่าของเซลล์ที่อยู่ใกล้เคียงจะถูกแชร์

0 0 0 0 0 0 0 0

  0 0 1 0 0 0

0 0 0 0 0 0 0 0

  0 0 0 1 0 0

0 0 0 0 0 0 0 0

ขั้นตอนของ CA ที่กฎคือเซลล์กลางหกเหลี่ยม = Sum (เพื่อนบ้าน)

0 0 1 1 0 0 0

  0 1 1 1 0 0

0 0 1 2 1 0 0

  0 0 1 1 1 0 0

0 0 0 1 1 0 0

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

0 0 0 0 0 0 0 0

  0 0 1 0 0 0

0 0 0 1 0 0 0

  0 0 0 0 0 0

0 0 0 0 0 0 0 0

หลังจากการทำซ้ำ

0 0 1 1 0 0 0

  0 1 2 2 0 0

0 0 2 2 1 0 0

  0 0 1 1 0 0

0 0 0 0 0 0 0 0

ตัวอย่างที่ 3 ไม่มีความสัมพันธ์

  0 0 0 0 0 0

0 0 1 0 0 0 0

  0 0 0 0 0 0

0 0 0 0 0 0 0 0

  0 0 0 1 0 0

0 0 0 0 0 0 0 0

หลังจากการทำซ้ำ

  0 1 1 0 0 0

0 1 1 1 0 0 0

  0 1 1 0 0 0

0 0 0 1 1 0 0

  0 0 1 1 1 0 0

0 0 0 1 1 0 0


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

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

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

เช่นลองนึกภาพว่าเราต้องการตรวจจับการชนกันของเซลล์ (5.7) บนเซลออโตมาตาและผลรวมที่ดำเนินการ (เพื่อนบ้านของเซลล์ (5,7)) และถ้าค่าเท่ากับ 8 และหากไม่มีการชนกันจะยิ่งกว่า 8 จะไม่ชนกัน ควรอยู่ในฟังก์ชันที่ประเมินแต่ละเซลล์เพื่อกำหนดสถานะถัดไปของเซลล์ในออโตมาติกเซลลูลาร์แบบอะซิงโครนัส การตรวจจับการชนกันของแต่ละเซลล์เป็นกฎท้องถิ่นที่เกี่ยวข้องกับเซลล์ข้างเคียงเท่านั้น
jlopez1967

ใช่ แต่คำถามที่เราต้องสามารถตอบเพื่อให้ขนานกับ CA แบบอะซิงโครนัสไม่ใช่ "มีการชนกันในเซลล์ (5,7)" แต่ "มีการชนกันที่ใดที่หนึ่งบนตารางและถ้าเป็นเช่นนั้น มัน?" ไม่สามารถตอบได้หากไม่มีการวนซ้ำข้ามกริด
นาธาเนียล

1

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

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

ci, cj = choose a pair at random.

int locked = 0;

/* Try to lock the cell ci. */
if ( atomicCAS( &lock[ci] , 0 , 1 ) == 0 ) {

    /* Try to lock the cell cj. */
    if ( atomicCAS( &lock[cj] , 0 , 1 ) == 0 ) {

        /* Now try to lock all the neigbourhood cells. */
        for ( cn = indices of all neighbours )
            if ( atomicCAS( &lock[cn] , 0 , 1 ) != 0 )
                break;

        /* If we hit a break above, we have to unroll all the locks. */
        if ( cn < number of neighbours ) {
            lock[ci] = 0;
            lock[cj] = 0;
            for ( int i = 0 ; i < cn ; i++ )
                lock[i] = 0;
            }

        /* Otherwise, we've successfully locked-down the neighbourhood. */
        else
            locked = 1;

        }

    /* Otherwise, back off. */
    else
        lock[ci] = 0;
    }

/* If we got everything locked-down... */
if ( locked ) {

    do whatever needs to be done...

    /* Release all the locks. */
    lock[ci] = 0;
    lock[cj] = 0;
    for ( int i = 0 ; i < cn ; i++ )
        lock[i] = 0;

    }

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

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

โปรดทราบว่าฉันกำลังเร็วและหลวมด้วยสัญกรณ์ในลูปของiเพื่อนบ้าน

ภาคผนวก:ฉันเป็นนักรบมากพอที่จะสรุปได้ว่าคุณสามารถถอยออกมาได้เมื่อต้องปะทะกัน ถ้ากรณีนี้ไม่ได้แล้วคุณสามารถตัดทุกอย่างที่เป็นของบรรทัดที่สองในwhile-loop และเพิ่มbreakในตอนท้ายของรอบสุดท้ายif-statement

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

ภาคผนวก 2:ทำไม่ถูกล่อลวงเพื่อเพิ่มการโทรไปยัง__syncthreads()ทุกที่ในรหัสนี้โดยเฉพาะอย่างยิ่งมันรุ่นบ่วงอธิบายไว้ในภาคผนวกที่ผ่านมา! Asynchronicity มีความสำคัญในการหลีกเลี่ยงการชนซ้ำในกรณีหลัง


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

1

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

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

__global__ void markPoints(Cell *grid, int gridWidth, int *posX, int *posY)
{
    int id = blockIdx.x * blockDim.x + threadIdx.x;
    int x, y;
    generateRandomCoord(&x, &y);
    posX[id] = x;
    posY[id] = y;
    grid[y * gridWidth + x].flag = 1;
}

__global__ void checkPoints(Cell *grid, int gridWidth, int *posX, int *posY, bool *active)
{
    int id = blockIdx.x * blockDim.x + threadIdx.x;
    int x = posX[id];
    int y = posY[id];
    int markedNeighbors = 
        grid[(y - 1) * gridWidth + x + 0].flag +
        grid[(y - 1) * gridWidth + x + 1].flag +
        grid[(y + 0) * gridWidth + x - 1].flag +
        grid[(y + 0) * gridWidth + x + 1].flag +
        grid[(y + 1) * gridWidth + x + 0].flag +
        grid[(y + 1) * gridWidth + x + 1].flag;
    active[id] = (markedNeighbors > 0);
}


__global__ void update(Cell *grid, int gridWidth, int *posX, int *posY, bool *active)
{
    int id = blockIdx.x * blockDim.x + threadIdx.x;
    int x = posX[id];
    int y = posY[id];
    grid[y * gridWidth + x].flag = 0;
    if (active[id]) {
        // do your fancy stuff here
    }
}

int main() 
{
  // alloc grid here, update up to k cells simultaneously
  int n = 1024 * 1024;
  int k = 1234;
  for (;;) {
      markPoints<<<gridDim,blockDim>>>(grid, gridWidth, posX, posY);
      checkPoints<<<gridDim,blockDim>>>(grid, gridWidth, posX, posY, active);
      update<<<gridDim,blockDim>>>(grid, gridWidth, posX, posY, active);
  }
}

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

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


0

ฉันแนะนำให้คุณเห็นลิงค์นี้http://www.wolfram.com/training/courses/hpc021.htmlประมาณ 15 นาทีครึ่งในวิดีโอของหลักสูตรการฝึกอบรมทางคณิตศาสตร์ที่พวกเขาทำการติดตั้ง automata เซลลูลาร์โดยใช้ CUDA จากที่นั่นและคุณสามารถแก้ไขได้


น่าเสียดายที่นั่นคือ CA แบบซิงโครนัสซึ่งเป็นสัตว์ประเภทต่างจากอะซิงโครนัสที่ฉันติดต่อด้วย ใน CA แบบซิงโครนัสเซลล์ทุกเซลล์จะได้รับการอัปเดตพร้อมกันและนี่เป็นเรื่องง่ายที่จะขนานกับ GPU แต่ในอะซิงโครนัส CA เซลล์ที่เลือกแบบสุ่มเดียวจะได้รับการอัปเดตทุกขั้นตอน การขนานนั้นยากกว่ามาก ปัญหาที่ระบุไว้ในคำถามของฉันนั้นขึ้นอยู่กับความต้องการฟังก์ชั่นการอัพเดทแบบอะซิงโครนัส
นาธาเนียล
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.