วิธีการสำหรับ HLO แบบไม่พร้อมกัน

  1. การเพิ่มการดำเนินการแบบไม่พร้อมกันไปยัง HLO จะเป็นเรื่องยุ่งยาก (เช่น all-reduce-start และ all-reduce-done)
  2. การแยกตอนเริ่มต้นและเสร็จสิ้นอาจไม่เพียงพอสำหรับการใช้งานที่ไม่พร้อมกันบางอย่าง กรณี

เพื่อกำหนดเป้าหมายข้อบกพร่องแรก เราเสนอที่จะแนะนำชุดย่อยล่าสุด opcode แบบอะซิงโครนัส: kAsyncStart, kAsyncUpdate และ kAsyncDone แนวคิด คือการสร้าง opcode แบบอะซิงโครนัสทั่วไปที่สามารถรวมคำสั่ง HLO ใดๆ การดำเนินการจริงที่จะดำเนินการแบบไม่พร้อมกันจะเข้ารหัสโดยใช้ การคำนวณที่เรียกว่าที่มีเพียงคำสั่งเป็นราก พารามิเตอร์สำหรับอินพุต การจัดการและนามแฝงอินพุต/เอาต์พุตที่ใช้งานอยู่ สามารถแชร์สำหรับการดำเนินการแบบไม่พร้อมกันใดก็ได้ คำสั่งแบบ async-start รูปร่างเอาต์พุตจะเป็น Tuple ของตัวถูกดำเนินการอินพุต ค่าเอาต์พุต และพารามิเตอร์ใดๆ สถานะระดับกลางที่จำเป็นสำหรับasync-updateหรือasync-done วิธีทำ

%async_op {
  %param0 = f32[64] parameter(0)
  ROOT %op = f32[32] op(f32[64] %param0), op_specific_attr=foo
}

%async-start = (f32[64], f32[32], s32[]) async-start(f32[64] %operand),
                                         calls=%async_op
%async-done = f32[32] async-done((f32[64], f32[32], s32[]) %async-start)

ในการนําเสนอข้างต้น มีเพียง async-start เท่านั้นที่มีการคำนวณที่เรียกว่า การหาสิ่งที่ async-done ทำโดยอ้างอิงตัวถูกดำเนินการเพื่อ ค้นหา async-start ที่เกี่ยวข้องเพื่อหาการคำนวณที่เรียกว่า

และโปรดทราบ องค์ประกอบแรกใน Tuple เอาต์พุตของชื่อแทน async-start ที่มีพารามิเตอร์ ตัวถูกดำเนินการ ดังนั้นบัฟเฟอร์จะยังคงทำงานอยู่จนกระทั่งถึงคำสั่งแบบอะซิงโครนัสเป็นอย่างน้อย ในทำนองเดียวกัน ชื่อแทนองค์ประกอบที่ 2 ที่มีเอาต์พุตเป็น async-done และ องค์ประกอบที่ 3 คือสถานะบริบทที่ใช้เพื่อติดตาม การทำงานไม่พร้อมกัน การแสดงนี้ยังรองรับ Tensor หลายรายการใน อินพุตและ/หรือเอาต์พุตการทำงานแบบอะซิงโครนัส และชื่อแทนจะทำงานเหมือนกัน ทาง:

%async_op {
  %param0 = f32[64] parameter(0)
  %param1 = f32[64] parameter(1)
  ROOT %op = (f32[32], f32[32]) op(f32[64] %param0, f32[64] %param1),
                                op_specific_attr=foo
}

%async-start = ((f32[64], f32[64]), (f32[32], f32[32]), s32[])
               async-start(f32[64] %operand0, f32[64] %operand1),
               calls=%async_op
%async-done = (f32[32], f32[32]) async-done(%async-start)

นอกจากนี้ ยังจะแตกลายของฝ่ายตรงข้ามเป็น 0 หรือมากกว่านั้นได้ด้วย async-update ขั้นตอนที่ดำเนินการคำนวณระดับกลาง การใช้ชื่อแทนอินพุต/เอาต์พุต ในลักษณะเดียวกันกับคำสั่ง async-update และ async-start และ วิธีการของ async-update ต้องมีผู้ใช้ 1 คนที่ไม่ใช่อีกคน async-update หรือ async-done:

%async_op {
  %param0 = f32[64] parameter(0)
  ROOT %op = f32[32] op(f32[64] %param0), op_specific_attr=foo
}

%async-start = (f32[64], f32[32], s32[]) async-start(f32[64] %operand),
                                         calls=%async_op
%async-update0 = (f32[64], f32[32], s32[]) async-update(
                           (f32[64], f32[32], s32[]) %async-start)
%async-update1 = (f32[64], f32[32], s32[]) async-update(
                           (f32[64], f32[32], s32[]) %async-update0)
%async-done = f32[32] async-done((f32[64], f32[32], s32[]) %async-update1)

ไวยากรณ์ sugar

เนื่องจากมีการคำนวณแยกต่างหากเพื่อกำหนดการดำเนินการที่จะ การดำเนินการแบบอะซิงโครนัสอาจยุ่งยากเล็กน้อย นอกจากนี้ เรายังขอเสนอการปรับน้ำตาลทางไวยากรณ์เพื่อ พิมพ์และแยกวิเคราะห์การทำงานที่ไม่พร้อมกันโดยอัตโนมัติราวกับเป็นการทำงานเฟิร์สคลาส รหัสการดำเนินการ แนวคิดคือให้ใช้คำต่อท้าย "-start", "-update" และ "-done" โดยการสร้างการคำนวณและการสอนโดยอัตโนมัติ (โดยไม่ต้อง ต่อท้าย) เมื่อแยกวิเคราะห์ ตัวอย่างเช่น ข้อมูลโค้ดด้านบนอาจพิมพ์ออกมาได้ ดังต่อไปนี้ และแยกวิเคราะห์ทั้ง 2 รายการให้อยู่ในรูปแบบเดียวกัน

%op-start = (f32[64], f32[32], s32[]) op-start(f32[64] %operand),
                                      op_specific_attr=foo
%op-update0 = (f32[64], f32[32], s32[]) op-update(
                        (f32[64], f32[32], s32[]) %op-start),
                        op_specific_attr=foo
%op-update1 = (f32[64], f32[32], s32[]) op-update(
                        (f32[64], f32[32], s32[]) %op-update0)
%op-done = f32[32] op-done((f32[64], f32[32], s32[]) %op-update1)

ผู้ตรวจสอบจะไม่อนุญาตให้มีการดำเนินการเพื่อไม่สร้างความสับสน จะต้องรวมอยู่ใน async-start หากเรากำหนด opcode อย่างชัดแจ้งสำหรับสิ่งนั้น ที่มีคำต่อท้าย "-start" และ/หรือ "-done" นี่เป็นการหลบหนีเช่นกัน ในกรณีที่มีคำสั่งที่จำเป็นต้องใช้การรักษาระดับ HLO ซึ่ง ไม่พอดีกับโมเดลที่อธิบายข้างต้น (เช่น อินพุต/เอาต์พุตที่เป็นชื่อแทน บัฟเฟอร์) ดังนั้น ในตอนแรก copy-start/copy-done collective-permute-start/collective-permute-done ฯลฯ จะใช้ต่อไป opcode ระดับเฟิร์สคลาสที่เกี่ยวข้องแทน รหัสดำเนินการ async-start/async-done รหัสจนกว่าเราจะทำความสะอาดรหัสเพื่อนำรหัสเหล่านี้ออก รหัสการดำเนินการ "-start"/"-done"