เร่งสปีด BEV Pooling บน NVIDIA GPU: กุญแจสำคัญสู่ AI ทางกายภาพ

เทคโนโลยี AI กำลังก้าวไปอีกขั้น โดยเฉพาะอย่างยิ่งในโลกของยานยนต์ไร้คนขับ (AVs), หุ่นยนต์, และระบบ AI เชิงพื้นที่ แนวคิดที่เรียกว่า Bird's-Eye-View (BEV) Perception กำลังได้รับความนิยมมากขึ้นเรื่อยๆ แนวคิดนี้คือการฉายภาพจากกล้องหลายตัวมาวางซ้อนกันบนแผนที่มุมมองจากด้านบน เพื่อให้ระบบ AI มองเห็นภาพรวมของสภาพแวดล้อมได้อย่างสอดคล้องกัน ทำให้การวิเคราะห์สิ่งต่างๆ เช่น เลนถนน, ยานพาหนะ, คนเดินเท้า, และพื้นที่ว่าง ทำได้ง่ายขึ้น

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

อย่างไรก็ตาม ในทางปฏิบัติ BEV Pooling อาจกลายเป็นคอขวดที่ทำให้ระบบช้าลงได้ เนื่องจากต้องจัดการกับการเข้าถึงหน่วยความจำที่ไม่สม่ำเสมอ, การอ่านค่าดัชนีซ้ำๆ, การรวมข้อมูลแบบกระจาย (scatter-reduce), และพฤติกรรมเฉพาะของแคชบน GPU

บทความนี้จะพาไปเจาะลึกถึง BEVPoolV3 ซึ่งเป็นกรณีศึกษาในการปรับปรุงประสิทธิภาพของ BEV Pooling และโอเปอเรเตอร์อื่น ๆ ที่มีการเรียกใช้ข้อมูลแบบ gather หรือ scatter บน NVIDIA GPU โดยจะแนะนำขั้นตอนที่นำไปปรับใช้ได้จริงกับปริมาณงานของคุณ: การจำแนกประเภทของหน่วยความจำที่ใช้งาน, การลดปริมาณการส่งข้อมูลแบบ scatter ที่ซ้ำซ้อน, การจับคู่การทำงานของเคอร์เนลให้เข้ากับสถาปัตยกรรม GPU เป้าหมาย, และการตรวจสอบจุดที่เป็นคอขวดด้วย NVIDIA Nsight Compute ผลการทดสอบประสิทธิภาพจะแสดงให้เห็นว่าทำไมขั้นตอนเหล่านี้ถึงสำคัญ เพราะ BEV Pooling แบบเดียวกัน อาจต้องการกลยุทธ์การปรับปรุงที่แตกต่างกัน ขึ้นอยู่กับว่าชุดข้อมูลที่ใช้งานนั้นอยู่ในหน่วยความจำหลัก (DRAM) หรืออยู่ในแคช L2 ของ GPU

BEVPoolV3: นวัตกรรมลดความหน่วงของ BEV Pooling บน NVIDIA RTX GPU

ก่อนหน้านี้ BEVPoolV2 (หรือ V2) ได้วางรากฐานที่สำคัญด้วยการปรับปรุง BEV Pooling ให้เหมาะกับการใช้งานจริงสำหรับโมเดลสไตล์ BEVDet และ CUDA-BEVFusion ได้พัฒนา bevpoolhalfpack10_kernel (หรือ V2+DO) ซึ่งใช้การวนซ้ำแบบ depth-outer เพื่อลดการโหลดดัชนีของไทล์ภายนอกที่ซ้ำซ้อนใน V2

BEVPoolV3 ต่อยอดการปรับปรุงนี้ด้วยการเปลี่ยนแปลงสำคัญ 4 ประการ:

  • ลดการโหลดข้อมูลความลึกที่ซ้ำซ้อน: ทำให้การเข้าถึงข้อมูลมีประสิทธิภาพมากขึ้น
  • แผนผัง scatter แบบ 5-array INT32: ช่วยให้การจัดเก็บและเรียกใช้ข้อมูลมีระเบียบและรวดเร็ว
  • ดัชนีที่คำนวณไว้ล่วงหน้า: ขจัดปัญหาการหารเลขจำนวนเต็มขณะทำงาน (runtime integer division)
  • การเขียนผลลัพธ์แบบ interval-owned: ป้องกันการทำงานซ้ำซ้อนในการเขียนข้อมูล

การเปลี่ยนแปลงเหล่านี้ส่งผลให้ลดความหน่วง (latency) ลงได้อย่างมากในหลากหลายสภาวะการใช้งานของหน่วยความจำ GPU

การจำแนกประเภทหน่วยความจำ: ก้าวแรกสู่การปรับปรุงประสิทธิภาพ

ขั้นตอนแรกที่สำคัญคือการประเมินว่าชุดข้อมูลที่ BEV Pooling ใช้งานนั้น สามารถเก็บอยู่ในแคช L2 ของ GPU ได้ทั้งหมดหรือไม่ ในกรณีศึกษาทั่วไป พบว่าข้อมูลหลักมีขนาดประมาณ 49 MB ซึ่งมากกว่าขนาดแคช L2 ของ NVIDIA RTX A6000 (6 MB) แต่เล็กกว่าขนาดแคช L2 ของ NVIDIA RTX PRO 6000 Blackwell Max-Q (128 MB)

การตัดสินใจว่าข้อมูล "พอดี" หรือ "ไม่พอดี" ใน L2 นี้ จะเป็นตัวกำหนดเป้าหมายของการปรับปรุง:

  • สำหรับ GPU ที่ L2 มีขนาดเล็ก (เช่น RTX A6000): เส้นทางการทำงานจะเน้นการลดปริมาณข้อมูลที่ต้องอ่าน/เขียน และการจัดเก็บผลลัพธ์แบบแคช-สตรีมมิ่ง เพื่อไม่ให้ข้อมูลดัชนีที่จำเป็นถูกลบออกจาก L2
  • สำหรับ GPU ที่ L2 มีขนาดใหญ่ (เช่น RTX PRO 6000 Blackwell Max-Q): เมื่อชุดข้อมูลสามารถเก็บใน L2 ได้ เส้นทางการทำงานจะเปลี่ยนไปเน้นประสิทธิภาพของคำสั่ง, การใช้งานทรัพยากร GPU ให้เต็มที่ (occupancy), ดัชนีที่คำนวณไว้ล่วงหน้า, การโหลดข้อมูลแบบเวกเตอร์, และการใช้ประโยชน์จาก FP8

การลดปริมาณการส่งข้อมูลแบบ Scatter ที่ซ้ำซ้อน

กระบวนการ BEV scatter-reduce โดยทั่วไปสามารถสรุปได้ดังนี้:

  • BEVPoolV2: วนลูปผ่านไทล์ของแชนเนลนอกลูป scatter สำหรับ C=80 และไทล์ 8 แชนเนล, ดัชนี scatter เดียวกันจะถูกโหลดถึง 10 ครั้ง ทำให้เกิดปริมาณข้อมูลดัชนีประมาณ 25.1 MB ทั้งที่จริงแล้วต้องการเพียง 2.51 MB หากโหลดเพียงครั้งเดียว
  • การใช้ Depth-Outer Loop Order: แก้ปัญหานี้ได้เกือบทั้งหมด โดยการวนลูปผ่านแต่ละช่วง (interval) ของ BEV ก่อน แล้วจึงรวบรวมแชนเนลทั้งหมดสำหรับช่วงนั้นในครั้งเดียว
  • BEVPoolV3: ขยายแนวคิดการปรับปรุงนี้ โดยเพิ่มการเปลี่ยนแปลงในการใช้งานอีก 4 ประการ เพื่อเพิ่มความเข้ากันได้และประสิทธิภาพในหลากหลายสภาวะหน่วยความจำ GPU:
  • ลดการโหลดข้อมูลความลึกที่ซ้ำซ้อนภายในแต่ละช่วง
  • ใช้แผนผัง scatter แบบ 5-array INT32 (ประกอบด้วย ranksdepth, ranksfeat, ranksbev, intervalstarts, และ interval_lengths)
  • ใช้ดัชนีที่ระบุชัดเจนซึ่งคำนวณไว้ล่วงหน้า ขจัดปัญหาการหารเลขจำนวนเต็มขณะทำงาน
  • ใช้การเขียนผลลัพธ์แบบ interval-owned ซึ่งหลีกเลี่ยงการใช้ atomic operations เมื่อเทียบกับเส้นทางสไตล์ V2

แผนผัง scatter แบบ 5-array มีความสำคัญอย่างยิ่งบน GPU ที่มี L2 ขนาดใหญ่ การรวม (packing) ranksdepth, ranksfeat, ranks_bev เป็น 3-array int ทำให้ได้ข้อมูลขนาด 12 ไบต์ ซึ่งอาจไม่สะดวกสำหรับการทำธุรกรรมหน่วยความจำที่จัดแนว (aligned memory transactions) และไม่เข้ากันกับการโหลด LDG.128 ขนาด 16 ไบต์ การใช้ array INT32 แยกกัน ช่วยให้เธรดที่อยู่ติดกันสามารถรวมการโหลดที่จัดแนวได้ และหลีกเลี่ยงการเชื่อมโยงฟิลด์ข้อมูล ทำให้สตรีมคำสั่งสะอาดขึ้น

การใช้ Interval-Owned Scatter-Reduce

ในการใช้งานจริง BEVPoolV3 ใช้เคอร์เนลเฉพาะทางหลายตัว แต่แนวคิดหลักของการใช้งานนั้น เข้าใจได้ง่ายผ่านโครงสร้างโค้ดอย่างง่าย: แผนผัง scatter จะถูกเตรียมไว้ล่วงหน้า แต่ละช่วง (BEV interval) จะถูกกำหนดเจ้าของ (owner) เจ้าของจะวนสำรวจจุดต่างๆ ในช่วงนั้น รวบรวมแชนเนลข้อมูลที่เกี่ยวข้อง แล้วจึงเขียนผลลัพธ์เพียงครั้งเดียว

โครงสร้างนี้ช่วยลดภาระในการถอดรหัสภายในลูปที่เกิดขึ้นเมื่อแผนผัง scatter ถูกรวมเป็นเรคคอร์ดเดียว แทนที่จะต้องสร้างดัชนีขณะทำงาน (runtime) เคอร์เนลจะอ่าน array ที่ระบุชัดเจน เช่น ranksdepth, ranksfeat, ranksbev, intervalstarts, และ interval_lengths

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

เคอร์เนลที่ใช้งานจริงจะปรับแต่งโครงสร้างนี้ให้เข้ากับสภาวะหน่วยความจำของ GPU เป้าหมาย:

  • บน GPU L2 ขนาดเล็ก (เช่น RTX A6000): การใช้งานจะเน้นการลดปริมาณข้อมูล, การสะสมแบบ half2 ใน FP16, และการเขียนผลลัพธ์แบบแคช-สตรีมมิ่ง เพื่อให้เทนเซอร์ผลลัพธ์ไม่ไปแย่งพื้นที่ข้อมูลดัชนีที่มีค่าใน L2
  • บน GPU L2 ขนาดใหญ่ (เช่น RTX PRO 6000 Blackwell Max-Q): การใช้งานจะเริ่มต้นด้วยการจับคู่สภาพแวดล้อมการทำงานที่มี occupancy สูง, จากนั้นลดภาระคำสั่งด้วยดัชนีที่คำนวณไว้ล่วงหน้า, การโหลดดัชนีแบบเวกเตอร์, และลูปภายในที่ปรับให้เหมาะสมกับ FP8 เมื่อชุดข้อมูลอยู่ใน L2

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

ผลลัพธ์ความหน่วงที่วัดได้บน RTX PRO 6000 Blackwell Max-Q แสดงให้เห็นว่าเส้นทางสำหรับ L2 ขนาดใหญ่ทำงานอย่างไรเมื่อเทียบกับจำนวนจุดและแชนเนลที่แตกต่างกัน รูปแบบการปรับปรุงเดียวกันนี้ยังคงใช้ได้กับเส้นทางที่ผูกกับ DRAM บน RTX A6000 โดยวัดจากอัตราเร่งเมื่อเทียบกับ V2 FP16 บน RTX A6000 เส้นทาง FP16 ที่ปรับให้เข้ากับ DRAM ของ V3 สามารถเร่งความเร็วได้ถึง 11-22 เท่าเมื่อเทียบกับ V2 ในการตั้งค่าต่างๆ ที่ทดสอบ บน RTX PRO 6000 Blackwell Max-Q, V3 FP8 สามารถเร่งความเร็วได้ถึง 11-42 เท่าเมื่อเทียบกับ V2 โดยอัตราเร่งที่มากที่สุดจะปรากฏเมื่อมีจำนวนจุดและแชนเนลที่กว้างขึ้น

การใช้งานและตรวจสอบ TensorRT Plugin

BEVPoolV3 ถูกนำเสนอในรูปแบบของ TensorRT IPluginV3 operator โดย plugin นี้จะรับแผนผัง scatter แบบ 5-array พร้อมกับข้อมูลความลึกและฟีเจอร์ แล้วจึงเลือกเคอร์เนลที่เหมาะสมสำหรับคลาส GPU และประเภทข้อมูล (dtype) ที่ใช้งาน เส้นทางการทดสอบประสิทธิภาพใช้การสร้างแบบ ONNX-to-TensorRT และการเล่นซ้ำด้วย CUDA Graph ผ่าน trtexec

สำหรับการตรวจสอบความถูกต้อง ควรเปรียบเทียบกับผลลัพธ์อ้างอิงแบบ FP64 หรือเส้นทาง V2 ที่เชื่อถือได้ บน RTX A6000, เคอร์เนลที่ปรับให้เข้ากับ DRAM ของ V3 ผ่านการตรวจสอบผลลัพธ์ทั้งหมดในการตั้งค่า 6 แบบ ด้วยค่า atol=1e-2 โดยมีข้อผิดพลาดสูงสุดที่สังเกตได้คือ 0.0065 บน RTX PRO 6000 Blackwell Max-Q, V2 และ V3 ให้ผลลัพธ์เหมือนกันในการตั้งค่าที่ทดสอบ ซึ่งแสดงว่าการปรับปรุงแผนผัง scatter และการตั้งค่าการทำงาน (launch configuration) นั้น ไม่ได้เปลี่ยนแปลงพฤติกรรมเชิงตัวเลขของเส้นทางอ้างอิง

การจับคู่อัลกอริทึมกับฮาร์ดแวร์

การเปลี่ยนแปลงอัลกอริทึมทั้ง 4 ประการของ BEVPoolV3 นั้นสามารถนำไปใช้ได้หลากหลาย แต่เคอร์เนลที่ใช้งานจริงจะต้องสอดคล้องกับจุดที่เป็นคอขวดของ GPU การตัดสินใจที่สำคัญคือ ชุดข้อมูลของ BEV-pooling สามารถเก็บอยู่ใน L2 ได้หรือไม่

บน RTX A6000, ชุดข้อมูลทั่วไปมีขนาดใหญ่เกิน L2 ดังนั้นเคอร์เนลจะต้อง ... (เนื้อหาถูกตัดตอน)


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

#BEVPooling #NVIDIA #GPU #AI #AutonomousVehicles #Robotics

ขอบคุณ แหล่งข้อมูล
https://developer.nvidia.com/blog/accelerating-bev-pooling-on-nvidia-gpus-for-physical-ai-applications/

เร่งสปีด BEV Pooling บน NVIDIA GPU: กุญแจสำคัญสู่ AI ทางกายภาพเทคโนโลยี AI กำลังก้าวไปอีกขั้น โดยเฉพาะอย่างยิ่งในโลกของยานยนต์ไร้คนขับ (AVs), หุ่นยนต์, และระบบ AI เชิงพื้นที่ แนวคิดที่เรียกว่า Bird's-Eye-View (BEV) Perception กำลังได้รับความนิยมมากขึ้นเรื่อยๆ แนวคิดนี้คือการฉายภาพจากกล้องหลายตัวมาวางซ้อนกันบนแผนที่มุมมองจากด้านบน เพื่อให้ระบบ AI มองเห็นภาพรวมของสภาพแวดล้อมได้อย่างสอดคล้องกัน ทำให้การวิเคราะห์สิ่งต่างๆ เช่น เลนถนน, ยานพาหนะ, คนเดินเท้า, และพื้นที่ว่าง ทำได้ง่ายขึ้นหัวใจสำคัญของกระบวนการนี้คือ BEV Pooling ซึ่งทำหน้าที่รวบรวมข้อมูลภาพจากกล้อง, ถ่วงน้ำหนักด้วยข้อมูลความลึก, แล้วนำไปรวมกันเป็นตาราง BEV การทำงานนี้ช่วยแปลงมุมมองที่แตกต่างกันของกล้องแต่ละตัว ให้กลายเป็นภาพรวมเดียวที่สอดคล้องกันในเชิงพื้นที่ ทำให้โมดูลอื่นๆ สามารถประมวลผลได้ง่ายขึ้น และที่สำคัญคือ ช่วยให้ระบบสามารถทำงานได้แบบ เรียลไทม์อย่างไรก็ตาม ในทางปฏิบัติ BEV Pooling อาจกลายเป็นคอขวดที่ทำให้ระบบช้าลงได้ เนื่องจากต้องจัดการกับการเข้าถึงหน่วยความจำที่ไม่สม่ำเสมอ, การอ่านค่าดัชนีซ้ำๆ, การรวมข้อมูลแบบกระจาย (scatter-reduce), และพฤติกรรมเฉพาะของแคชบน GPUบทความนี้จะพาไปเจาะลึกถึง BEVPoolV3 ซึ่งเป็นกรณีศึกษาในการปรับปรุงประสิทธิภาพของ BEV Pooling และโอเปอเรเตอร์อื่น ๆ ที่มีการเรียกใช้ข้อมูลแบบ gather หรือ scatter บน NVIDIA GPU โดยจะแนะนำขั้นตอนที่นำไปปรับใช้ได้จริงกับปริมาณงานของคุณ: การจำแนกประเภทของหน่วยความจำที่ใช้งาน, การลดปริมาณการส่งข้อมูลแบบ scatter ที่ซ้ำซ้อน, การจับคู่การทำงานของเคอร์เนลให้เข้ากับสถาปัตยกรรม GPU เป้าหมาย, และการตรวจสอบจุดที่เป็นคอขวดด้วย NVIDIA Nsight Compute ผลการทดสอบประสิทธิภาพจะแสดงให้เห็นว่าทำไมขั้นตอนเหล่านี้ถึงสำคัญ เพราะ BEV Pooling แบบเดียวกัน อาจต้องการกลยุทธ์การปรับปรุงที่แตกต่างกัน ขึ้นอยู่กับว่าชุดข้อมูลที่ใช้งานนั้นอยู่ในหน่วยความจำหลัก (DRAM) หรืออยู่ในแคช L2 ของ GPUBEVPoolV3: นวัตกรรมลดความหน่วงของ BEV Pooling บน NVIDIA RTX GPUก่อนหน้านี้ BEVPoolV2 (หรือ V2) ได้วางรากฐานที่สำคัญด้วยการปรับปรุง BEV Pooling ให้เหมาะกับการใช้งานจริงสำหรับโมเดลสไตล์ BEVDet และ CUDA-BEVFusion ได้พัฒนา bevpoolhalfpack10_kernel (หรือ V2+DO) ซึ่งใช้การวนซ้ำแบบ depth-outer เพื่อลดการโหลดดัชนีของไทล์ภายนอกที่ซ้ำซ้อนใน V2BEVPoolV3 ต่อยอดการปรับปรุงนี้ด้วยการเปลี่ยนแปลงสำคัญ 4 ประการ:ลดการโหลดข้อมูลความลึกที่ซ้ำซ้อน: ทำให้การเข้าถึงข้อมูลมีประสิทธิภาพมากขึ้นแผนผัง scatter แบบ 5-array INT32: ช่วยให้การจัดเก็บและเรียกใช้ข้อมูลมีระเบียบและรวดเร็วดัชนีที่คำนวณไว้ล่วงหน้า: ขจัดปัญหาการหารเลขจำนวนเต็มขณะทำงาน (runtime integer division)การเขียนผลลัพธ์แบบ interval-owned: ป้องกันการทำงานซ้ำซ้อนในการเขียนข้อมูลการเปลี่ยนแปลงเหล่านี้ส่งผลให้ลดความหน่วง (latency) ลงได้อย่างมากในหลากหลายสภาวะการใช้งานของหน่วยความจำ GPUการจำแนกประเภทหน่วยความจำ: ก้าวแรกสู่การปรับปรุงประสิทธิภาพขั้นตอนแรกที่สำคัญคือการประเมินว่าชุดข้อมูลที่ BEV Pooling ใช้งานนั้น สามารถเก็บอยู่ในแคช L2 ของ GPU ได้ทั้งหมดหรือไม่ ในกรณีศึกษาทั่วไป พบว่าข้อมูลหลักมีขนาดประมาณ 49 MB ซึ่งมากกว่าขนาดแคช L2 ของ NVIDIA RTX A6000 (6 MB) แต่เล็กกว่าขนาดแคช L2 ของ NVIDIA RTX PRO 6000 Blackwell Max-Q (128 MB)การตัดสินใจว่าข้อมูล "พอดี" หรือ "ไม่พอดี" ใน L2 นี้ จะเป็นตัวกำหนดเป้าหมายของการปรับปรุง:สำหรับ GPU ที่ L2 มีขนาดเล็ก (เช่น RTX A6000): เส้นทางการทำงานจะเน้นการลดปริมาณข้อมูลที่ต้องอ่าน/เขียน และการจัดเก็บผลลัพธ์แบบแคช-สตรีมมิ่ง เพื่อไม่ให้ข้อมูลดัชนีที่จำเป็นถูกลบออกจาก L2สำหรับ GPU ที่ L2 มีขนาดใหญ่ (เช่น RTX PRO 6000 Blackwell Max-Q): เมื่อชุดข้อมูลสามารถเก็บใน L2 ได้ เส้นทางการทำงานจะเปลี่ยนไปเน้นประสิทธิภาพของคำสั่ง, การใช้งานทรัพยากร GPU ให้เต็มที่ (occupancy), ดัชนีที่คำนวณไว้ล่วงหน้า, การโหลดข้อมูลแบบเวกเตอร์, และการใช้ประโยชน์จาก FP8การลดปริมาณการส่งข้อมูลแบบ Scatter ที่ซ้ำซ้อนกระบวนการ BEV scatter-reduce โดยทั่วไปสามารถสรุปได้ดังนี้:BEVPoolV2: วนลูปผ่านไทล์ของแชนเนลนอกลูป scatter สำหรับ C=80 และไทล์ 8 แชนเนล, ดัชนี scatter เดียวกันจะถูกโหลดถึง 10 ครั้ง ทำให้เกิดปริมาณข้อมูลดัชนีประมาณ 25.1 MB ทั้งที่จริงแล้วต้องการเพียง 2.51 MB หากโหลดเพียงครั้งเดียวการใช้ Depth-Outer Loop Order: แก้ปัญหานี้ได้เกือบทั้งหมด โดยการวนลูปผ่านแต่ละช่วง (interval) ของ BEV ก่อน แล้วจึงรวบรวมแชนเนลทั้งหมดสำหรับช่วงนั้นในครั้งเดียวBEVPoolV3: ขยายแนวคิดการปรับปรุงนี้ โดยเพิ่มการเปลี่ยนแปลงในการใช้งานอีก 4 ประการ เพื่อเพิ่มความเข้ากันได้และประสิทธิภาพในหลากหลายสภาวะหน่วยความจำ GPU:ลดการโหลดข้อมูลความลึกที่ซ้ำซ้อนภายในแต่ละช่วงใช้แผนผัง scatter แบบ 5-array INT32 (ประกอบด้วย ranksdepth, ranksfeat, ranksbev, intervalstarts, และ interval_lengths)ใช้ดัชนีที่ระบุชัดเจนซึ่งคำนวณไว้ล่วงหน้า ขจัดปัญหาการหารเลขจำนวนเต็มขณะทำงานใช้การเขียนผลลัพธ์แบบ interval-owned ซึ่งหลีกเลี่ยงการใช้ atomic operations เมื่อเทียบกับเส้นทางสไตล์ V2แผนผัง scatter แบบ 5-array มีความสำคัญอย่างยิ่งบน GPU ที่มี L2 ขนาดใหญ่ การรวม (packing) ranksdepth, ranksfeat, ranks_bev เป็น 3-array int ทำให้ได้ข้อมูลขนาด 12 ไบต์ ซึ่งอาจไม่สะดวกสำหรับการทำธุรกรรมหน่วยความจำที่จัดแนว (aligned memory transactions) และไม่เข้ากันกับการโหลด LDG.128 ขนาด 16 ไบต์ การใช้ array INT32 แยกกัน ช่วยให้เธรดที่อยู่ติดกันสามารถรวมการโหลดที่จัดแนวได้ และหลีกเลี่ยงการเชื่อมโยงฟิลด์ข้อมูล ทำให้สตรีมคำสั่งสะอาดขึ้นการใช้ Interval-Owned Scatter-Reduceในการใช้งานจริง BEVPoolV3 ใช้เคอร์เนลเฉพาะทางหลายตัว แต่แนวคิดหลักของการใช้งานนั้น เข้าใจได้ง่ายผ่านโครงสร้างโค้ดอย่างง่าย: แผนผัง scatter จะถูกเตรียมไว้ล่วงหน้า แต่ละช่วง (BEV interval) จะถูกกำหนดเจ้าของ (owner) เจ้าของจะวนสำรวจจุดต่างๆ ในช่วงนั้น รวบรวมแชนเนลข้อมูลที่เกี่ยวข้อง แล้วจึงเขียนผลลัพธ์เพียงครั้งเดียวโครงสร้างนี้ช่วยลดภาระในการถอดรหัสภายในลูปที่เกิดขึ้นเมื่อแผนผัง scatter ถูกรวมเป็นเรคคอร์ดเดียว แทนที่จะต้องสร้างดัชนีขณะทำงาน (runtime) เคอร์เนลจะอ่าน array ที่ระบุชัดเจน เช่น ranksdepth, ranksfeat, ranksbev, intervalstarts, และ interval_lengthsโครงสร้างโค้ดนี้แสดงให้เห็นถึงรูปแบบทั่วไปของ BEVPoolV3: แผนผัง scatter มีความชัดเจน, การถอดรหัสดัชนีขณะทำงานถูกยกเลิก, ข้อมูลความลึกถูกโหลดในลูปของเจ้าของช่วง, และแต่ละเซลล์ผลลัพธ์จะถูกเขียนเพียงครั้งเดียวหลังจากการสะสมข้อมูลภายใน (local accumulation)เคอร์เนลที่ใช้งานจริงจะปรับแต่งโครงสร้างนี้ให้เข้ากับสภาวะหน่วยความจำของ GPU เป้าหมาย:บน GPU L2 ขนาดเล็ก (เช่น RTX A6000): การใช้งานจะเน้นการลดปริมาณข้อมูล, การสะสมแบบ half2 ใน FP16, และการเขียนผลลัพธ์แบบแคช-สตรีมมิ่ง เพื่อให้เทนเซอร์ผลลัพธ์ไม่ไปแย่งพื้นที่ข้อมูลดัชนีที่มีค่าใน L2บน GPU L2 ขนาดใหญ่ (เช่น RTX PRO 6000 Blackwell Max-Q): การใช้งานจะเริ่มต้นด้วยการจับคู่สภาพแวดล้อมการทำงานที่มี occupancy สูง, จากนั้นลดภาระคำสั่งด้วยดัชนีที่คำนวณไว้ล่วงหน้า, การโหลดดัชนีแบบเวกเตอร์, และลูปภายในที่ปรับให้เหมาะสมกับ FP8 เมื่อชุดข้อมูลอยู่ใน L2หลักการสำคัญของอัลกอริทึมยังคงเหมือนเดิม: เป็นเจ้าของช่วง, หลีกเลี่ยงการถอดรหัสดัชนีขณะทำงาน, สะสมข้อมูลภายใน, และเขียนเพียงครั้งเดียว ส่วนการปรับปรุงเฉพาะสำหรับสถาปัตยกรรมฮาร์ดแวร์จะเปลี่ยนวิธีการนำหลักการนั้นไปใช้, แต่ไม่ได้เปลี่ยนสิ่งที่ BEV-pooling operator คำนวณผลลัพธ์ความหน่วงที่วัดได้บน RTX PRO 6000 Blackwell Max-Q แสดงให้เห็นว่าเส้นทางสำหรับ L2 ขนาดใหญ่ทำงานอย่างไรเมื่อเทียบกับจำนวนจุดและแชนเนลที่แตกต่างกัน รูปแบบการปรับปรุงเดียวกันนี้ยังคงใช้ได้กับเส้นทางที่ผูกกับ DRAM บน RTX A6000 โดยวัดจากอัตราเร่งเมื่อเทียบกับ V2 FP16 บน RTX A6000 เส้นทาง FP16 ที่ปรับให้เข้ากับ DRAM ของ V3 สามารถเร่งความเร็วได้ถึง 11-22 เท่าเมื่อเทียบกับ V2 ในการตั้งค่าต่างๆ ที่ทดสอบ บน RTX PRO 6000 Blackwell Max-Q, V3 FP8 สามารถเร่งความเร็วได้ถึง 11-42 เท่าเมื่อเทียบกับ V2 โดยอัตราเร่งที่มากที่สุดจะปรากฏเมื่อมีจำนวนจุดและแชนเนลที่กว้างขึ้นการใช้งานและตรวจสอบ TensorRT PluginBEVPoolV3 ถูกนำเสนอในรูปแบบของ TensorRT IPluginV3 operator โดย plugin นี้จะรับแผนผัง scatter แบบ 5-array พร้อมกับข้อมูลความลึกและฟีเจอร์ แล้วจึงเลือกเคอร์เนลที่เหมาะสมสำหรับคลาส GPU และประเภทข้อมูล (dtype) ที่ใช้งาน เส้นทางการทดสอบประสิทธิภาพใช้การสร้างแบบ ONNX-to-TensorRT และการเล่นซ้ำด้วย CUDA Graph ผ่าน trtexecสำหรับการตรวจสอบความถูกต้อง ควรเปรียบเทียบกับผลลัพธ์อ้างอิงแบบ FP64 หรือเส้นทาง V2 ที่เชื่อถือได้ บน RTX A6000, เคอร์เนลที่ปรับให้เข้ากับ DRAM ของ V3 ผ่านการตรวจสอบผลลัพธ์ทั้งหมดในการตั้งค่า 6 แบบ ด้วยค่า atol=1e-2 โดยมีข้อผิดพลาดสูงสุดที่สังเกตได้คือ 0.0065 บน RTX PRO 6000 Blackwell Max-Q, V2 และ V3 ให้ผลลัพธ์เหมือนกันในการตั้งค่าที่ทดสอบ ซึ่งแสดงว่าการปรับปรุงแผนผัง scatter และการตั้งค่าการทำงาน (launch configuration) นั้น ไม่ได้เปลี่ยนแปลงพฤติกรรมเชิงตัวเลขของเส้นทางอ้างอิงการจับคู่อัลกอริทึมกับฮาร์ดแวร์การเปลี่ยนแปลงอัลกอริทึมทั้ง 4 ประการของ BEVPoolV3 นั้นสามารถนำไปใช้ได้หลากหลาย แต่เคอร์เนลที่ใช้งานจริงจะต้องสอดคล้องกับจุดที่เป็นคอขวดของ GPU การตัดสินใจที่สำคัญคือ ชุดข้อมูลของ BEV-pooling สามารถเก็บอยู่ใน L2 ได้หรือไม่บน RTX A6000, ชุดข้อมูลทั่วไปมีขนาดใหญ่เกิน L2 ดังนั้นเคอร์เนลจะต้อง ... (เนื้อหาถูกตัดตอน)หมายเหตุ: ข้อมูลต้นทางอาจมีการตัดตอนในส่วนท้ายของเนื้อหา ทำให้ไม่สามารถให้ข้อมูลที่สมบูรณ์ได้ อย่างไรก็ตาม ข้อมูลที่นำเสนอข้างต้นได้สรุปประเด็นสำคัญเกี่ยวกับ BEVPoolV3 และแนวทางการปรับปรุงประสิทธิภาพบน NVIDIA GPU ตามข้อมูลที่มีอยู่#BEVPooling #NVIDIA #GPU #AI #AutonomousVehicles #Roboticshttps://developer.nvidia.com/blog/accelerating-bev-pooling-on-nvidia-gpus-for-physical-ai-applications/
Shared content
DEVELOPER.NVIDIA.COM
Accelerating BEV Pooling on NVIDIA GPUs for Physical AI Applications
An increasingly common design pattern for autonomous vehicles (AVs), robotics, and spatial AI systems is bird’s-eye-view (BEV) perception. BEV models project multicamera image features into a shared…
5 التعليقات 0 المشاركات 450 مشاهدة 0 معاينة