การวิเคราะห์การจัดทำดัชนี

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

ตัวอย่าง

สำหรับการออกอากาศจาก tensor<20xf32> ถึง tensor<10x20x30xf32>

p0 = f32[20] parameter(0)
bc0 = f32[10, 20, 30] broadcast(p0), dimensions={1}

การแมปการจัดทำดัชนีจากเอาต์พุตถึงอินพุตคือ \((i, j, k) \mapsto (j)\) สำหรับ $i \in [0, 10]\(, \)j \in [0, 20]\( and \)k \in [0, 30]$

แรงจูงใจ

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

การประสาน

การให้เหตุผลเกี่ยวกับการรวมหน่วยความจำกลายเป็นเรื่องที่เป็นไปได้สำหรับกรณีที่ไม่สำคัญเมื่อเราทราบว่ามีการอ่านองค์ประกอบ/ส่วนของอินพุตเพื่อประมวลผลองค์ประกอบของเอาต์พุต

ตัวถูกดำเนินการประโยชน์

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

การแปลงรหัสวิดีโอโดยใช้ไทล์

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

ฟังก์ชันและโดเมน

แมปการจัดทำดัชนีคือฟังก์ชัน \(\boldsymbol{f}(\boldsymbol{d}, \boldsymbol{s})\) ที่แมปดัชนีแบบหลาย \(\boldsymbol{d}\) ของ tensor \(A\) กับองค์ประกอบ/ช่วงของ tensor \(B\)พารามิเตอร์ \(\boldsymbol{s}\) หมายถึงช่วงดัชนีของมิติข้อมูลที่แสดงใน tensor \(B\)แต่ไม่ใช่ tensor \(A\)

ตัวอย่างเช่น หากเราลดลงจาก tensor<2x4x8x16xf32> เป็น tensor<4x8xf32> การแมปการจัดทำดัชนีจากเอาต์พุต 2 มิติเป็นอินพุต 4 มิติจะเป็น\((d_0, d_1) \mapsto (s_0, d_0, d_1, s_1)\)โดยที่ \(d_i\) คือพารามิเตอร์มิติข้อมูลที่สอดคล้องกับดัชนี Tensor เอาต์พุต พารามิเตอร์ \(s_j\) จะเข้ารหัสหลายค่า กล่าวคือ เพื่อคำนวณ \((d_0, d_1)\) องค์ประกอบของผลลัพธ์ เราจำเป็นต้องมี \((s_0, d_0, d_1, s_1)\) องค์ประกอบของอินพุต โดยที่ \(s_0 \in [0, 2)\) และ \(s_1 \in [0, 16)\)

การแมปนี้สร้างขึ้นจากแอตทริบิวต์ของคำสั่ง HLO หรืออาจเขียนการแมปของวิธีการที่ไม่ได้รวมเข้าด้วยกันเพื่อรับการจัดทำดัชนีสำหรับฟิวชัน นอกจากนี้ การแมปยังมีโดเมนซึ่งระบุองค์ประกอบของ tensor ที่การแมปที่มีอยู่

\[ \begin{eqnarray} \boldsymbol{f}(\boldsymbol{d}, \boldsymbol{s})\; &s.t.& \\ \boldsymbol{lb}_d &\leq& \boldsymbol{d} \leq \boldsymbol{ub}_d \\ \boldsymbol{lb}_s &\leq& \boldsymbol{s} \leq \boldsymbol{ub}_s \\ \boldsymbol{lb}_g &\leq& \boldsymbol{g}(\boldsymbol{d}, \boldsymbol{s}) \leq \boldsymbol{ub}_g \end{eqnarray} \]

เนื่องจากเราต้องการลดการคำนวณใหม่ให้เหลือน้อยที่สุด เราจึงต้องมีไลบรารีสำหรับการคำนวณเชิงสัญลักษณ์ XLA อาศัย MLIR อยู่แล้ว เราจึงใช้ mlir::AffineMap แทนการเขียนไลบรารีเลขคณิตสัญลักษณ์

AffineMapทั่วไปจะมีหน้าตาดังนี้

(d0)[s0, s1] -> (s0 + 5, d0 * 2, s1 * 3 + 50)

AffineMap มีพารามิเตอร์ 2 ประเภทด้วยกัน ได้แก่ มิติข้อมูลและสัญลักษณ์ที่เรานำมาใช้ \(\boldsymbol d\) และ \(\boldsymbol s\) ตามลำดับ AffineMap ไม่มีข้อมูลเมตาเกี่ยวกับช่วงของมิติข้อมูล เราจึงต้องจัดหาข้อมูลนี้ด้วยตนเอง

struct Range {
 int64_t lower_bound;
 int64_t upper_bound;
};

struct IndexingMap {
 mlir::AffineMap affine_map;
 std::vector<Range> dimension_ranges;
 std::vector<Range> symbol_ranges;
 llvm::DenseMap<mlir::AffineExpr, Range> expr_ranges;
};

dim_ranges จะเข้ารหัสข้อจำกัดกล่อง inclusive สำหรับพารามิเตอร์มิติข้อมูล \(\boldsymbol{d}\) ของแมปการจัดทำดัชนี ซึ่งมักจะสอดคล้องกับรูปร่างของ Tensor เอาต์พุตสำหรับการดำเนินการ เช่น สลับตำแหน่ง ลด องค์ประกอบ จุด แต่มีข้อยกเว้นบางอย่าง เช่น HloConcatenateInstruction

symbol_ranges เข้ารหัสค่าที่เป็นไปได้ที่ \(\boldsymbol {s}\) พารามิเตอร์ทำได้

ลองดูตัวอย่างเพื่อทำความเข้าใจความหมายของข้อความข้างต้น

แผนที่การจัดทำดัชนีสำหรับการดำเนินการที่ไม่ได้รวม

Elementwise

สำหรับ Ops แบบองค์ประกอบ แมปการจัดทำดัชนีคือข้อมูลประจำตัว

  p0 = f32[10, 20] parameter(0)
  p1 = f32[10, 20] parameter(1)
  add = f32[10, 20] add(p0, p1)

เอาต์พุตของอินพุตแมป:

  • เอาต์พุต -> Input_0: \((d_0, d_1) \mapsto (d_0, d_1)\) สำหรับ $\boldsymbol{d} \in [0,9] \times [0, 19]\(, i.e. \)\boldsymbol{d} \in {\rm Dom}(เอาต์พุต)$
  • เอาต์พุต -> Input_1: \((d_0, d_1) \mapsto (d_0, d_1)\) สำหรับ $\boldsymbol{d} \in {\rm Dom} (เอาต์พุต)$

อินพุตที่จะส่งออกแมป

  • Input_i -> เอาต์พุต: \((d_0, d_1) \mapsto (d_0, d_1)\) สำหรับ $\boldsymbol{d} \in {\rm Dom}(เอาต์พุต)$

ประกาศ

การออกอากาศหมายความว่ามิติข้อมูลบางส่วนจะถูกนำออกเมื่อเราจับคู่เอาต์พุตกับอินพุต และเมื่อเราจับคู่อินพุตกับเอาต์พุต

p0 = f32[20] parameter(0)
bc0 = f32[10, 20, 30] broadcast(p0), dimensions={1}

เอาต์พุตที่จะป้อนการแมป:

  • เอาต์พุต -> อินพุต: \((d_0, d_1, d_2) \mapsto (d_1)\) สำหรับ $\boldsymbol{d} \in {\rm Dom}(เอาต์พุต)$

อินพุตไปยังเอาต์พุตแมป

  • อินพุต -> เอาต์พุต: \((d_0) \mapsto (s_0, d_1, s_1)\) สำหรับ $\boldsymbol{d} \in {\rm Dom}(เอาต์พุต)\( and \)\boldsymbol{s} \in [0, 9] \times [0, 29]$

โปรดทราบว่าตอนนี้เรามี \(\boldsymbol s\) ทางด้านขวาสำหรับการแมปอินพุตกับเอาต์พุต สัญลักษณ์เหล่านั้นคือสัญลักษณ์ที่แสดงถึงช่วงของค่า ตัวอย่างเช่น ในกรณีนี้ ทุกองค์ประกอบของอินพุตที่มีดัชนี \(d_0\) จะแมปกับส่วนเอาต์พุตขนาด 10x1x30

ค่าคงที่และไอโอตา

เพื่อความสะดวก พารามิเตอร์เหล่านี้ไม่มีพารามิเตอร์อินพุต จึงไม่มีสิ่งใดที่จะต้องคำนวณการจัดทำดัชนี

สลับ

แมปการจัดทำดัชนีสําหรับการสับเปลี่ยนเป็นการเรียงสับเปลี่ยนมิติข้อมูลอินพุต/เอาต์พุต

p0 = f32[3, 12288, 6, 128] parameter(0)
transpose = f32[3, 6, 128, 12288] transpose(p0), dimensions={0, 2, 3, 1}

เอาต์พุตที่จะป้อนการแมป:

  • เอาต์พุต -> อินพุต: \((d_0, d_1, d_2, d_3) \mapsto (d_0, d_3, d_1, d_2)\) สำหรับ\(\boldsymbol{d} \in {\rm Dom}(output)\)

อินพุตไปยังเอาต์พุตแมป:

  • อินพุต -> เอาต์พุต: \((d_0, d_1, d_2, d_3) \mapsto (d_0, d_2, d_3, d_1)\) สำหรับ\(\boldsymbol{d} \in {\rm Dom}(input)\)

รีเวิร์ส

การแมปการจัดทำดัชนีสำหรับแบบย้อนกลับจะเปลี่ยนมิติข้อมูลที่เปลี่ยนกลับเป็น $upper_bound(d_i) - d_i$:

p0 = f32[1, 17, 9, 9] parameter(0)
reverse = f32[1, 17, 9, 9] reverse(p0), dimensions={1, 2}

เอาต์พุตที่จะป้อนการแมป:

  • เอาต์พุต -> อินพุต: $(d_0, d_1, d_2, d_3) \mapsto (d_0, -d_1 + 16, -d_2 + 8, d_3)\( for \)\boldsymbol{d} \in {\rm Dom}(เอาต์พุต)$

อินพุตไปยังเอาต์พุตแมป:

  • อินพุต -> เอาต์พุต: $(d_0, d_1, d_2, d_3) \mapsto (d_0, -d_1 + 16, -d_2 + 8, d_3)\( for \)\boldsymbol{d} \in {\rm Dom}(ข้อมูล)$

(Variadic)Reduce (ลด)

การลดตาม Variadic มีอินพุตหลายรายการและหลาย Init แล้ว แผนที่จากเอาต์พุตสู่อินพุตจะเพิ่มขนาดที่ลดลง ดังนั้นจึงเหมือนจะผกผันกับการออกอากาศ

p0 = f32[256,10] parameter(0)
p0_init = f32[] constant(-inf)
p1 = s32[256,10] parameter(1)
p1_init = s32[] constant(0)
reduce = (f32[10], s32[10]) reduce(p0, p1, p0_init, p1_init),
  dimensions={0}, to_apply=min

เอาต์พุตของอินพุตแมป:

  • เอาต์พุต -> Input_j: \((d_0) \mapsto (s_0, d_0)\) สำหรับ $\boldsymbol{d} \in {\rm Dom}(เอาต์พุต)\( and \)\boldsymbol{s} \in [0, 9]$
  • เอาต์พุต -> init_j: \((d_0) \mapsto ()\) สำหรับ $\boldsymbol{d} \in {\rm Dom}(เอาต์พุต)$

อินพุตที่จะส่งออกแมป

  • Input_i -> export_j: \((d_0, d_1) \mapsto (d_1)\) สำหรับ $\boldsymbol{d} \in {\rm Dom}(input)$
  • init_i -> export_j: \(() \mapsto (s_0)\) สำหรับ \(\boldsymbol{s} \in [0, 9]\)

สำหรับ \(i, j = 0, \ldots, INPUT\\_COUNT\)

Slice

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

p0 = f32[10, 20, 50] parameter(0)
slice = f32[5, 3, 25] slice(f32[10, 20, 50] p0),
  slice={[5:10:1], [3:20:7], [0:50:2]}

เอาต์พุตที่จะป้อนการแมป:

  • เอาต์พุต -> อินพุต: \((d_0, d_1, d_2) \mapsto (d_0 + 5, 7d_1 + 3, 2d_2)\) สำหรับ\(\boldsymbol{d} \in {\rm Dom}(output)\)

อินพุตไปยังเอาต์พุตแมป:

  • อินพุต -> เอาต์พุต: \((d_0, d_1, d_2) \mapsto (d_0, d_1 / 7, d_2 / 2)\) สำหรับ \(\boldsymbol{d} \in [5, 9] \times [3, 19] \times [0, 49]\) ก้าวย่าง $[1, 7, 2]$

จะแจ้งภายหลัง: การจัดทำดัชนีอินพุตต่อเอาต์พุต

ปรับรูปร่าง

การเปลี่ยนรูปแบบมีหลากหลายรสชาติ

ยุบรูปร่าง

นี่คือการเปลี่ยนรูปร่าง "เชิงเส้น" จาก N-D เป็น 1D

p0 = f32[4,8] parameter(0)
reshape = f32[32] reshape(p0)

เอาต์พุตที่จะป้อนการแมป:

  • เอาต์พุต -> อินพุต: \((d_0) \mapsto (d_0 / 8, d_0 \mod 8)\) สำหรับ $\boldsymbol{d} \ใน {\rm Dom}(เอาต์พุต)$

อินพุตไปยังเอาต์พุตแมป:

  • อินพุต -> เอาต์พุต: \((d_0, d_1) \mapsto (8 d_0 + d_1)\) สำหรับ $\boldsymbol{d} \in {\rm Dom}(input)$

ขยายรูปร่าง

นี่คือตัวเลือก "รูปร่างยุบ" แบบผกผัน โดยเปลี่ยนรูปร่างอินพุต 1 มิติเป็นเอาต์พุต N-D

p0 = f32[32] parameter(0)
reshape = f32[4, 8] reshape(p0)

เอาต์พุตที่จะป้อนการแมป:

  • เอาต์พุต -> อินพุต: \((d_0, d_1) \mapsto (8 d_0 + d_1)\) สำหรับ $\boldsymbol{d} \in {\rm Dom}(เอาต์พุต)$

อินพุตไปยังเอาต์พุตแมป:

  • อินพุต -> เอาต์พุต: \((d_0) \mapsto (d_0 / 8, d_0 \mod 8)\) สำหรับ $\boldsymbol{d} \in {\rm Dom}(input)$

การปรับรูปร่างทั่วไป

ต่อไปนี้เป็นการดำเนินการปรับรูปร่างที่ไม่จะแสดงเป็นรูปร่างขยายหรือยุบเดี่ยวไม่ได้ โฆษณาเหล่านี้สามารถแสดงเป็นองค์ประกอบหนึ่งของรูปร่างขยายหรือยุบ 2 รายการขึ้นไป

ตัวอย่างที่ 1: การแปลงเชิงเส้นเป็นเชิงเส้น
p0 = f32[4,8] parameter(0)
reshape = f32[2, 4, 4] reshape(p0)

การปรับรูปร่างนี้สามารถแสดงเป็นองค์ประกอบของรูปร่างยุบของ tensor<4x8xf32> ถึง tensor<32xf32> แล้วขยายรูปร่างเป็น tensor<2x4x4xf32>

เอาต์พุตที่จะป้อนการแมป:

  • เอาต์พุต -> อินพุต: $(d_0, d_1, d_2) \mapsto (2d_0 + (4d_1 + d_2) / 8, 4d_1 + d_2) \mod 8)$

เป็นเวลา \(\boldsymbol{d} \in {\rm Dom}(output)\)

อินพุตไปยังเอาต์พุตแมป:

  • อินพุต -> เอาต์พุต: $(d_0, d_1) \mapsto ((8d_0 + d_1) / 16, ((8d_0 + d_1) \mod 16) / 4, d_1 \mod 4)$

สำหรับ \(\boldsymbol{d} \in {\rm Dom}(input)\)

ตัวอย่างที่ 2: รูปร่างย่อยที่ขยายและยุบ
p0 = f32[4, 8, 12] parameter(0)
reshape = f32[32, 3, 4] reshape(p0)

การปรับรูปร่างนี้สามารถแสดงเป็นองค์ประกอบของการปรับรูปร่าง 2 แบบ รายการแรกจะยุบมิติข้อมูลด้านนอก tensor<4x8x12xf32> เป็น tensor<32x12xf32> และรายการที่ 2 ขยายมิติข้อมูลด้านในสุด tensor<32x12xf32> เป็น tensor<32x3x4xf32>

เอาต์พุตที่จะป้อนการแมป:

  • เอาต์พุต -> อินพุต: \((d_0, d_1, d_2) \mapsto (d_0 / 8, d_0 \mod 8, 4d_1 + d_2)\) สำหรับ \(\boldsymbol{d} \in {\rm Dom}(output)\)

อินพุตไปยังเอาต์พุตแมป:

  • อินพุต -> เอาต์พุต: \((d_0, d_1, d_2) \mapsto (8d_0 + d_1, d_2 / 4, d_2 \mod 4)\) สำหรับ \(\boldsymbol{d} \in {\rm Dom}(input)\)

บิตแคสต์

ออบเจ็กต์บิตแคสต์อาจแสดงเป็นลำดับของการสลับรูปร่างเปลี่ยนรูปร่างได้ ดังนั้น แผนที่การจัดทำดัชนีเป็นเพียงองค์ประกอบของแผนที่การจัดทำดัชนีสำหรับลำดับนี้

เชื่อมต่อ

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

p0 = f32[3,50] parameter(0)
p1 = f32[3,30] parameter(1)
concat = f32[3,80] concatenate(f32[3,50] p0, f32[3,30] p1),
  dimensions={1}

เอาต์พุตที่จะป้อนการแมป:

  • เอาต์พุต -> อินพุต 1:

\((d_0, d_1) \mapsto (d_0, d_1)\) สำหรับ \(\boldsymbol{d} \in [0, 2] \times [0, 49]\)

  • เอาต์พุต -> อินพุต 2:

\((d_0, d_1) \mapsto (d_0, d_1 - 50)\) สำหรับ $\boldsymbol{d} \in [0, 2] \times [50, 79]$

อินพุตที่จะส่งออกแมป:

  • อินพุต 1 -> เอาต์พุต: \((d_0, d_1) \mapsto (d_0, d_1)\) สำหรับ $\boldsymbol{d} \in {\rm Dom}(input_1)$
  • อินพุต 2 -> เอาต์พุต: \((d_0, d_1) \mapsto (d_0, d_1 + 50)\) สำหรับ $\boldsymbol{d} \in {\rm Dom}(input_2)$

จุด (ใช้เอาต์พุตไปยังอินพุต

แผนที่การจัดทำดัชนีสำหรับจุดคล้ายคลึงกับแผนที่การลด

p0 = f32[4, 128, 256] parameter(0)
p1 = f32[4, 256, 64] parameter(1)
dot = f32[4, 128, 64] dot(p0, p1),
  lhs_batch_dims={0}, rhs_batch_dims={0},
  lhs_contracting_dims={2}, rhs_contracting_dims={1}

เอาต์พุตไปยังอินพุตจะแมปดังนี้

  • เอาต์พุต -> Input_1: \((d_0, d_1, d_2) \mapsto (d_0, d_1, s_0)\) สำหรับ\(\boldsymbol{d} \in {\rm Dom}(output)\) และ \(\boldsymbol{s} \in [0, 255]\)
  • เอาต์พุต -> Input_2: \((d_0, d_1, d_2) \mapsto (d_0, s_0, d_2)\) สำหรับ\(\boldsymbol{d} \in {\rm Dom}(output)\) และ \(\boldsymbol{s} \in [0, 255]\)

อินพุตที่จะส่งออกแมป

  • อินพุต_1 -> เอาต์พุต: \((d_0, d_1, d_2) \mapsto (d_0, d_1, s_0)\) สำหรับ\(\boldsymbol{d} \in {\rm Dom}(input_1)\) และ \(\boldsymbol{s} \in [0, 63]\)
  • อินพุต_2 -> เอาต์พุต: \((d_0, d_1, d_2) \mapsto (d_0, s_0, d_1)\) สำหรับ\(\boldsymbol{d} \in {\rm Dom}(input_2)\) และ \(\boldsymbol{s} \in [0, 127]\)

ลดกรอบเวลา (จะแจ้งภายหลัง)

แผ่น (จะแจ้งภายหลัง)

การจัดทำดัชนีแผนที่สำหรับ Fusion

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

อินพุตเดียว แมปการจัดทำดัชนีหลายรายการ

นี่คือตัวอย่างสำหรับ \(p_0 + p_0^T\)

f {
  p0 = f32[1000, 1000] parameter(0)
  transpose_p0 = f32[1000, 1000]{0, 1} transpose(p0), dimensions={1, 0}
  ROOT a0 = f32[1000, 1000] add(p0, transpose_p0)
}

แมปการจัดทำดัชนีเอาต์พุตสู่อินพุตสำหรับ p0 จะเป็น $(d_0, d_1) \mapsto (d_0, d_1)\( and \)(d_0, d_1) \mapsto (d_1, d_0)$ ซึ่งหมายความว่าเราจะต้องอ่านพารามิเตอร์อินพุต 2 ครั้งเมื่อคำนวณองค์ประกอบเอาต์พุต 1 รายการ

ข้อมูล 1 รายการ แมปการจัดทำดัชนีที่ซ้ำกันออกแล้ว

img

มีบางกรณีที่แผนที่การจัดทำดัชนีจะเหมือนกัน แม้ว่าแผนที่การจัดทำดัชนีจะไม่ชัดเจนในทันทีก็ตาม

f {
  p0 = f32[20, 10, 50] parameter(0)
  lhs_transpose_1 = f32[10, 20, 50] transpose(p0), dimensions={1, 0, 2}
  lhs_e = f32[10, 20, 50] exponential(lhs_transpose_1)
  lhs_transpose_2 = f32[10, 50, 20] transpose(lhs_e), dimensions={0, 2, 1}
  rhs_transpose_1 = f32[50, 10, 20] transpose(p0), dimensions={2, 1, 0}
  rhs_log = f32[50, 10, 20] exponential(rhs_transpose_1)
  rhs_transpose_2 = f32[10, 50, 20] transpose(rhs_log), dimensions={1, 0, 2}
  ROOT add = f32[10, 50, 20] add(lhs_transpose_2, rhs_transpose_2)
}

แมปการจัดทำดัชนีเอาต์พุตไปยังอินพุตสำหรับ p0 ในกรณีนี้มีเพียง $(d_0, d_1, d_2) \mapsto (d_2, d_0, d_1)$

ซอฟต์แม็กซ์

img

การแมปการจัดทำดัชนีเอาต์พุตไปยังอินพุตสำหรับ parameter 0 สำหรับ Softmax มีดังนี้

  • \((d_0, d_1, d_2) \mapsto (d_0, d_1, d_2)\)
  • \((d_0, d_1, d_2)[s_0] \mapsto (d_0, d_1, s_0)\)

\(\boldsymbol{d} \in {\rm Dom}(output)\) และ \(\boldsymbol{s} \in [0, 124]\) หมายถึงมิติข้อมูลด้านในสุดของอินพุต

ตัวย่อของแผนที่การจัดทำดัชนี

ค่าเริ่มต้นอย่างง่ายสำหรับอัปสตรีม mlir::AffineMap ไม่สามารถตั้งสมมติฐานเกี่ยวกับช่วงของมิติข้อมูล/สัญลักษณ์ ดังนั้นจึงอธิบายนิพจน์ด้วย mod และ div อย่างมีประสิทธิภาพไม่ได้

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

เครื่องมือลดความซับซ้อนสามารถเขียนนิพจน์ต่อไปนี้ใหม่

  1. \((d_0, d_1) \mapsto (d_0 + d1 / 16, d1 \mod 16)\) สำหรับ $\boldsymbol{d} \in [0, 6] \time [0, 14]\( becomes \)(d_0, d_1) \mapsto (d_0, d_1)$
  2. $(d_0, d_1, d_2) \mapsto ((100d_0 + 10d_1 + d_2) /100, ((100d_0 + 10d_1 + d_2) \mod 100) / 10, d_2 \d_2, (100 วัน_0) \mod 100) / 10, d_2 \d_0, (100d_0)\( for \)\( becomes \)
  3. $(d_0, d_1, d_2) \mapsto ((16d_0 + 4d_1 + d_2) /8, (16d_0 + 4d_1 + d_2) \mod 8)\( for \)d_i \ใน [0, 9]\( becomes \)(d_0, ม็อด_2 + 4d_1)
  4. \((d_0, d_1) \mapsto (-(-11d_0 - d_1 + 109) / 11 + 9)\) สำหรับ $\boldsymbol{d} \in [0, 9] \times [0, 10]\( becomes \)(d_0, d_1) \mapsto (d_0)$

การแมปการจัดทำดัชนีที่ง่ายขึ้นช่วยให้เราเข้าใจว่าการเปลี่ยนรูปร่างบางส่วนใน HLO ยกเลิกกันเอง

p0 = f32[10, 10, 10] parameter(0)
reshape1 = f32[50, 20] reshape(p0)
reshape2 = f32[10, 10, 10] reshape(reshape1)

หลังจากการเรียบเรียงแผนที่การจัดทำดัชนีและการทำให้แผนที่เรียบง่ายขึ้น เราจะได้รับ

\((d_0, d_1, d_2) \mapsto (d_0, d_1, d_2)\).