การเพิ่มประสิทธิภาพกราฟ TensorFlow ด้วย Grappler

ดูบน TensorFlow.org ทำงานใน Google Colab ดูแหล่งที่มาบน GitHub ดาวน์โหลดโน๊ตบุ๊ค

ภาพรวม

TensorFlow ใช้ทั้งกราฟและการดำเนินการอย่างกระตือรือร้นเพื่อดำเนินการคำนวณ tf.Graph มีชุดของ tf.Operation (ops) ซึ่งแทนหน่วยของการคำนวณและ tf.Tensor ซึ่งแสดงถึงหน่วยของข้อมูลที่ไหลระหว่าง ops

Grappler คือระบบการเพิ่มประสิทธิภาพกราฟเริ่มต้นในรันไทม์ TensorFlow Grappler ใช้การปรับให้เหมาะสมในโหมดกราฟ (ภายใน tf.function ) เพื่อปรับปรุงประสิทธิภาพของการคำนวณ TensorFlow ของคุณผ่านการทำให้กราฟง่ายขึ้นและการเพิ่มประสิทธิภาพระดับสูงอื่นๆ เช่น ตัวฟังก์ชัน inlining เพื่อเปิดใช้งานการเพิ่มประสิทธิภาพระหว่างขั้นตอน การเพิ่มประสิทธิภาพ tf.Graph ยังช่วยลดการใช้หน่วยความจำสูงสุดของอุปกรณ์และปรับปรุงการใช้ฮาร์ดแวร์โดยปรับการแมปโหนดกราฟให้เหมาะสมเพื่อคำนวณทรัพยากร

ใช้ tf.config.optimizer.set_experimental_options() เพื่อการควบคุมที่ละเอียดยิ่งขึ้นในการเพิ่มประสิทธิภาพ tf.Graph ของคุณ

เครื่องมือเพิ่มประสิทธิภาพกราฟที่มีอยู่

Grappler ทำการเพิ่มประสิทธิภาพกราฟผ่านไดรเวอร์ระดับบนสุดที่เรียกว่า MetaOptimizer เครื่องมือเพิ่มประสิทธิภาพกราฟต่อไปนี้ใช้ได้กับ TensorFlow:

  • เครื่องมือเพิ่มประสิทธิภาพการพับคงที่ - อนุมานค่าเทนเซอร์แบบคงที่เมื่อเป็นไปได้โดยการพับโหนดคงที่ในกราฟและทำให้ผลลัพธ์เป็นจริงโดยใช้ค่าคงที่
  • เครื่องมือเพิ่มประสิทธิภาพเลขคณิต - ลดความซับซ้อนของการดำเนินการทางคณิตศาสตร์โดยกำจัดนิพจน์ย่อยทั่วไปและทำให้คำสั่งเลขคณิตง่ายขึ้น
  • เครื่องมือ เพิ่มประสิทธิภาพเลย์เอาต์ - ปรับเลย์เอาต์เทนเซอร์ให้เหมาะสมเพื่อดำเนินการตามรูปแบบข้อมูล เช่น การโน้มน้าวให้มีประสิทธิภาพมากขึ้น
  • เครื่องมือเพิ่มประสิทธิภาพ Remapper - ทำการแมปกราฟย่อยใหม่ไปยังการใช้งานที่มีประสิทธิภาพมากขึ้นโดยแทนที่กราฟย่อยที่เกิดขึ้นทั่วไปด้วยเมล็ดเสาหินที่หลอมรวมที่ปรับให้เหมาะสม
  • เครื่องมือเพิ่มประสิทธิภาพหน่วยความจำ - วิเคราะห์กราฟเพื่อตรวจสอบการใช้งานหน่วยความจำสูงสุดสำหรับแต่ละการทำงาน และแทรกการดำเนินการคัดลอกหน่วยความจำ CPU-GPU เพื่อสลับหน่วยความจำ GPU เป็น CPU เพื่อลดการใช้หน่วยความจำสูงสุด
  • เครื่องมือเพิ่มประสิทธิภาพการขึ้นต่อกัน - ลบหรือจัดเรียงการพึ่งพาการควบคุมใหม่ เพื่อทำให้เส้นทางวิกฤตสั้นลงสำหรับขั้นตอนของแบบจำลองหรือเปิดใช้งานการปรับให้เหมาะสมอื่นๆ ยังลบโหนดที่ไม่มีประสิทธิภาพเช่น Identity
  • เครื่องมือเพิ่มประสิทธิภาพการตัดแต่งกิ่ง - พรุนโหนดที่ไม่มีผลต่อผลลัพธ์จากกราฟ โดยปกติจะดำเนินการก่อนเพื่อลดขนาดของกราฟและเร่งการประมวลผลใน Grappler pass อื่นๆ
  • ตัว เพิ่มประสิทธิภาพฟังก์ชัน - เพิ่มประสิทธิภาพไลบรารีฟังก์ชันของโปรแกรม TensorFlow และเนื้อหาฟังก์ชันแบบอินไลน์เพื่อเปิดใช้งานการเพิ่มประสิทธิภาพระหว่างขั้นตอนอื่นๆ
  • เครื่องมือเพิ่มประสิทธิภาพรูปร่าง - ปรับกราฟย่อยที่ทำงานบนข้อมูลที่เกี่ยวข้องกับรูปร่างและรูปร่างให้เหมาะสม
  • เครื่องมือเพิ่มประสิทธิภาพอัตโนมัติขนาน - ขนานกราฟโดยอัตโนมัติโดยแยกตามมิติแบทช์ เครื่องมือเพิ่มประสิทธิภาพนี้ถูกปิดโดยค่าเริ่มต้น
  • เครื่องมือเพิ่มประสิทธิภาพลูป - ปรับโฟลว์การควบคุมกราฟให้เหมาะสมที่สุดโดยการยกกราฟย่อยที่ไม่คงที่ของลูปออกจากลูป และโดยการลบการดำเนินการสแต็คที่ซ้ำซ้อนในลูป ยังปรับลูปให้เหมาะสมด้วยจำนวนการเดินทางที่ทราบแบบสถิตและลบกิ่งที่หยุดทำงานที่ทราบแบบสถิตในเงื่อนไข
  • ตัวเพิ่มประสิทธิภาพตัวจัดสรรแบบกำหนดขอบเขต - แนะนำตัวจัดสรรแบบมีขอบเขตเพื่อลดการเคลื่อนที่ของข้อมูลและเพื่อรวมการดำเนินการบางอย่าง
  • ปักหมุดที่เครื่องมือเพิ่มประสิทธิภาพโฮสต์ - สลับการทำงานขนาดเล็กไปยัง CPU เครื่องมือเพิ่มประสิทธิภาพนี้ถูกปิดโดยค่าเริ่มต้น
  • เครื่องมือเพิ่มประสิทธิภาพความแม่นยำแบบผสมอัตโนมัติ - แปลงประเภทข้อมูลเป็น float16 ตามความเหมาะสมเพื่อปรับปรุงประสิทธิภาพ ปัจจุบันใช้ได้กับ GPU เท่านั้น
  • ผู้เป ลื่องดีบัก - ดึงโหนดที่เกี่ยวข้องกับการดำเนินการดีบัก เช่น tf.debugging.Assert , tf.debugging.check_numerics และ tf.print จากกราฟ เครื่องมือเพิ่มประสิทธิภาพนี้ถูกปิดโดยค่าเริ่มต้น

ติดตั้ง

import numpy as np
import timeit
import traceback
import contextlib


import tensorflow as tf

สร้างตัวจัดการบริบทเพื่อสลับสถานะเครื่องมือเพิ่มประสิทธิภาพอย่างง่ายดาย

@contextlib.contextmanager
def options(options):
  old_opts = tf.config.optimizer.get_experimental_options()
  tf.config.optimizer.set_experimental_options(options)
  try:
    yield
  finally:
    tf.config.optimizer.set_experimental_options(old_opts)

เปรียบเทียบประสิทธิภาพการดำเนินการที่มีและไม่มี Grappler

TensorFlow 2 และสูงกว่านั้นทำงาน อย่างกระตือรือร้น โดยค่าเริ่มต้น ใช้ tf.function เพื่อเปลี่ยนการดำเนินการเริ่มต้นเป็นโหมดกราฟ Grappler ทำงานโดยอัตโนมัติในพื้นหลังเพื่อใช้การเพิ่มประสิทธิภาพกราฟด้านบนและปรับปรุงประสิทธิภาพการดำเนินการ

เครื่องมือเพิ่มประสิทธิภาพการพับคงที่

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

def test_function_1():
  @tf.function
  def simple_function(input_arg):
    print('Tracing!')
    a = tf.constant(np.random.randn(2000,2000), dtype = tf.float32)
    c = a
    for n in range(50):
      c = c@a
    return tf.reduce_mean(c+input_arg)

  return simple_function

ปิดเครื่องมือเพิ่มประสิทธิภาพการพับคงที่และเรียกใช้ฟังก์ชัน:

with options({'constant_folding': False}):
  print(tf.config.optimizer.get_experimental_options())
  simple_function = test_function_1()
  # Trace once
  x = tf.constant(2.2)
  simple_function(x)
  print("Vanilla execution:", timeit.timeit(lambda: simple_function(x), number = 1), "s")
{'constant_folding': False, 'disable_model_pruning': False, 'disable_meta_optimizer': False}
Tracing!
Vanilla execution: 0.0018392090000816097 s

เปิดใช้งานเครื่องมือเพิ่มประสิทธิภาพการพับคงที่และเรียกใช้ฟังก์ชันอีกครั้งเพื่อสังเกตการเพิ่มความเร็วในการทำงานของฟังก์ชัน

with options({'constant_folding': True}):
  print(tf.config.optimizer.get_experimental_options())
  simple_function = test_function_1()
  # Trace once
  x = tf.constant(2.2)
  simple_function(x)
  print("Constant folded execution:", timeit.timeit(lambda: simple_function(x), number = 1), "s")
{'constant_folding': True, 'disable_model_pruning': False, 'disable_meta_optimizer': False}
Tracing!
Constant folded execution: 0.0006749789999958011 s

ดีบัก Stripper Optimizer

พิจารณาฟังก์ชันง่ายๆ ที่ตรวจสอบค่าตัวเลขของอาร์กิวเมนต์อินพุตและส่งกลับ

def test_function_2():
  @tf.function
  def simple_func(input_arg):
    output = input_arg
    tf.debugging.check_numerics(output, "Bad!")
    return output
  return simple_func

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

test_func = test_function_2()
p1 = tf.constant(float('inf'))
try:
  test_func(p1)
except tf.errors.InvalidArgumentError as e:
  traceback.print_exc(limit=2)
2021-09-22 20:34:55.871238: E tensorflow/core/kernels/check_numerics_op.cc:292] abnormal_detected_host @0x7f4878e00100 = {0, 1} Bad!
Traceback (most recent call last):
  File "/tmp/ipykernel_22954/3616845043.py", line 4, in <module>
    test_func(p1)
  File "/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/eager/def_function.py", line 885, in __call__
    result = self._call(*args, **kwds)
tensorflow.python.framework.errors_impl.InvalidArgumentError:  Bad! : Tensor had Inf values
     [[node CheckNumerics (defined at tmp/ipykernel_22954/2241890286.py:5) ]] [Op:__inference_simple_func_131]

Errors may have originated from an input operation.
Input Source operations connected to node CheckNumerics:
 input_arg (defined at tmp/ipykernel_22954/3616845043.py:4)

Function call stack:
simple_func

tf.debugging.check_numerics ทำให้เกิดข้อผิดพลาดอาร์กิวเมนต์ที่ไม่ถูกต้องเนื่องจากอาร์กิวเมนต์ Inf เป็น test_func

เปิดใช้งานเครื่องมือเพิ่มประสิทธิภาพการดีบัก Stripper และเรียกใช้ฟังก์ชันอีกครั้ง

with options({'debug_stripper': True}):
  test_func2 = test_function_2()
  p1 = tf.constant(float('inf'))
  try:
    test_func2(p1)
  except tf.errors.InvalidArgumentError as e:
    traceback.print_exc(limit=2)

เครื่องมือเพิ่มประสิทธิภาพดีบัก Stripper จะดึงโหนด tf.debug.check_numerics ออกจากกราฟและดำเนินการฟังก์ชันโดยไม่ทำให้เกิดข้อผิดพลาดใดๆ

สรุป

รันไทม์ TensorFlow ใช้ Grappler เพื่อปรับกราฟให้เหมาะสมโดยอัตโนมัติก่อนดำเนินการ ใช้ tf.config.optimizer.set_experimental_options เพื่อเปิดหรือปิดใช้งานเครื่องมือเพิ่มประสิทธิภาพกราฟต่างๆ

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับ Grappler โปรดดู ที่ TensorFlow Graph Optimizations