ผู้มอบสิทธิ์ GPU สำหรับ LiteRT

การใช้หน่วยประมวลผลกราฟิก (GPU) เพื่อเรียกใช้โมเดลแมชชีนเลิร์นนิง (ML) สามารถปรับปรุงประสิทธิภาพของโมเดลและประสบการณ์ของผู้ใช้ได้อย่างมาก ของแอปพลิเคชันที่พร้อมใช้งาน ML LiteRT ทำให้สามารถใช้ GPU และ โปรเซสเซอร์พิเศษอื่นๆ ผ่านทางไดรเวอร์ฮาร์ดแวร์ที่เรียกว่า ผู้แทน การเปิดใช้การใช้ GPU ด้วย LiteRT ML แอปพลิเคชันมีประโยชน์ดังต่อไปนี้

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

เอกสารนี้อธิบายภาพรวมการรองรับ GPU ใน LiteRT และบางส่วนของ การใช้งานขั้นสูงสำหรับหน่วยประมวลผล GPU สำหรับข้อมูลที่เจาะจงเพิ่มเติมเกี่ยวกับ การใช้การรองรับ GPU ในแพลตฟอร์มที่เฉพาะเจาะจง โปรดดูคำแนะนำต่อไปนี้

การสนับสนุนการดำเนินการ GPU ML

การดำเนินการหรือ Ops ของ TensorFlow ML อาจมีข้อจำกัดบางประการ ซึ่งได้รับการเร่งโดยผู้ได้รับมอบสิทธิ์ LiteRT GPU ผู้ที่ได้รับมอบสิทธิ์สนับสนุน การดำเนินการต่อไปนี้ในความแม่นยำการลอยตัวแบบ 16 บิตและ 32 บิต:

  • ADD
  • AVERAGE_POOL_2D
  • CONCATENATION
  • CONV_2D
  • DEPTHWISE_CONV_2D v1-2
  • EXP
  • FULLY_CONNECTED
  • LOGICAL_AND
  • LOGISTIC
  • LSTM v2 (Basic LSTM only)
  • MAX_POOL_2D
  • MAXIMUM
  • MINIMUM
  • MUL
  • PAD
  • PRELU
  • RELU
  • RELU6
  • RESHAPE
  • RESIZE_BILINEAR v1-3
  • SOFTMAX
  • STRIDED_SLICE
  • SUB
  • TRANSPOSE_CONV

โดยค่าเริ่มต้น ระบบจะรองรับการดำเนินการทั้งหมดในเวอร์ชัน 1 เท่านั้น การเปิดใช้งานการวัดปริมาณ support จะเปิดใช้เวอร์ชันที่เหมาะสม เช่น ADD เวอร์ชัน 2

การแก้ปัญหาการรองรับ GPU

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

WARNING: op code #42 cannot be handled by this delegate.

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

โมเดลตัวอย่าง

โมเดลตัวอย่างต่อไปนี้สร้างขึ้นเพื่อใช้ประโยชน์จากการเร่ง GPU ด้วย LiteRT และมีไว้เพื่อการอ้างอิงและการทดสอบ:

การเพิ่มประสิทธิภาพสำหรับ GPU

เทคนิคต่อไปนี้สามารถช่วยให้คุณได้รับประสิทธิภาพที่ดีขึ้นเมื่อเรียกใช้โมเดล บนฮาร์ดแวร์ GPU โดยใช้ผู้มอบสิทธิ์ LiteRT GPU:

  • การดำเนินการปรับรูปแบบ - การดำเนินการบางอย่างที่ดำเนินการอย่างรวดเร็วบน CPU อาจมี ต้นทุนที่สูงสำหรับ GPU บนอุปกรณ์เคลื่อนที่ การดำเนินการปรับรูปร่างโดยเฉพาะ มีค่าใช้จ่ายที่ต้องเรียกใช้ รวมถึง BATCH_TO_SPACE, SPACE_TO_BATCH SPACE_TO_DEPTH และอื่นๆ คุณควรตรวจสอบการใช้การปรับรูปร่างอย่างละเอียด และพิจารณาว่าอาจใช้สำหรับการสำรวจข้อมูลเท่านั้น หรือสำหรับการปรับปรุงโมเดลล่วงหน้า การนำคีย์เวิร์ดเหล่านี้ออกอาจมีความสำคัญ เพื่อปรับปรุงประสิทธิภาพ

  • แชแนลข้อมูลรูปภาพ - ใน GPU ข้อมูล tensor จะแบ่งเป็น 4 แชแนล และ การคำนวณบน Tensor ที่มีรูปร่าง [B,H,W,5] ทำได้เกี่ยวกับ เดียวกันบน Tensor ของรูปร่าง [B,H,W,8] แต่แย่กว่าอย่างเห็นได้ชัด [B,H,W,4] หากฮาร์ดแวร์กล้องที่คุณใช้สนับสนุนเฟรมรูปภาพ RGBA ป้อนอินพุตแบบ 4 ช่องให้เร็วขึ้นมากเนื่องจากหลีกเลี่ยง สำเนาหน่วยความจำจาก RGB 3 ช่องเป็น RGBX แบบ 4 ช่อง

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

การรองรับ GPU ขั้นสูง

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

การใช้โมเดลที่เล็กลง

ส่วนนี้จะอธิบายวิธีที่การมอบสิทธิ์ GPU เร่งความเร็วของโมเดล 8 บิต ซึ่งรวมถึงรายการต่อไปนี้

หากต้องการเพิ่มประสิทธิภาพ ให้ใช้โมเดลที่มีทั้งอินพุตที่เป็นจุดลอยตัวและ Tensor เอาต์พุต

คุณลักษณะนี้ทำงานอย่างไร

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

  • Tensor คงที่ (เช่น น้ำหนัก/อคติ) จะมีการลดค่าเชิงปริมาณเมื่อค่า หน่วยความจำ GPU การดำเนินการนี้จะเกิดขึ้นเมื่อเปิดใช้ผู้รับมอบสิทธิ์สำหรับ การอ่านเขียน

  • อินพุตและเอาต์พุตไปยังโปรแกรม GPU หากแปลงให้เป็นแบบ 8 บิตจะ ลดปริมาณและเชิงปริมาณ (ตามลำดับ) สำหรับการอนุมานแต่ละรายการ การดำเนินการนี้ ก็จะดำเนินการบน CPU โดยใช้เคอร์เนลที่เพิ่มประสิทธิภาพของ LiteRT

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

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

การลดเวลาเริ่มต้นด้วยการเรียงลำดับ

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

C++

    TfLiteGpuDelegateOptionsV2 options = TfLiteGpuDelegateOptionsV2Default();
    options.experimental_flags |= TFLITE_GPU_EXPERIMENTAL_FLAGS_ENABLE_SERIALIZATION;
    options.serialization_dir = kTmpDir;
    options.model_token = kModelToken;

    auto* delegate = TfLiteGpuDelegateV2Create(options);
    if (interpreter->ModifyGraphWithDelegate(delegate) != kTfLiteOk) return false;
      

Java

    GpuDelegate delegate = new GpuDelegate(
      new GpuDelegate.Options().setSerializationParams(
        /* serializationDir= */ serializationDir,
        /* modelToken= */ modelToken));

    Interpreter.Options options = (new Interpreter.Options()).addDelegate(delegate);
      

เมื่อใช้ฟีเจอร์การทำให้เป็นอนุกรม ให้ตรวจสอบว่าโค้ดเป็นไปตามข้อกำหนดเหล่านี้ กฎการใช้งาน

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