تحسين الرسم البياني TensorFlow مع Grappler

عرض على TensorFlow.org تشغيل في Google Colab عرض المصدر على جيثب تحميل دفتر

ملخص

يستخدم TensorFlow كلاً من الرسم البياني وعمليات التنفيذ الحثيثة لتنفيذ العمليات الحسابية. يحتوي tf.Graph على مجموعة من كائنات tf.Operation (العمليات) التي تمثل وحدات الحساب وكائنات tf.Tensor التي تمثل وحدات البيانات التي تتدفق بين العمليات.

Grappler هو نظام تحسين الرسم البياني الافتراضي في وقت تشغيل TensorFlow. يطبق Grappler التحسينات في وضع الرسم البياني (ضمن tf.function ) لتحسين أداء حسابات TensorFlow الخاصة بك من خلال تبسيط الرسم البياني والتحسينات الأخرى عالية المستوى مثل تضمين هيئات الوظائف لتمكين التحسينات بين الإجراءات. يؤدي تحسين tf.Graph أيضًا إلى تقليل استخدام ذاكرة الجهاز في الذروة وتحسين استخدام الأجهزة عن طريق تحسين تعيين عقد الرسم البياني لحساب الموارد.

استخدم tf.config.optimizer.set_experimental_options() للتحكم بشكل أفضل في تحسينات tf.Graph .

أدوات تحسين الرسم البياني المتاحة

يقوم Grappler بإجراء تحسينات على الرسم البياني من خلال برنامج تشغيل عالي المستوى يسمى MetaOptimizer . تتوفر أدوات تحسين الرسم البياني التالية مع TensorFlow:

  • مُحسِّن الطي الثابت - يستنتج بشكل ثابت قيمة الموترات عندما يكون ذلك ممكنًا عن طريق طي العقد الثابتة في الرسم البياني ويتجسد النتيجة باستخدام الثوابت.
  • مُحسِّن حسابي - يبسط العمليات الحسابية عن طريق التخلص من التعبيرات الفرعية الشائعة وتبسيط العبارات الحسابية.
  • مُحسِّن التخطيط - يُحسِّن تخطيطات الموتر لتنفيذ عمليات تعتمد على تنسيق البيانات مثل التلافيف بكفاءة أكبر.
  • مُحسِّن Remapper - يعيد تعيين الرسوم البيانية الفرعية على تطبيقات أكثر كفاءة عن طريق استبدال الرسوم البيانية الفرعية التي تحدث بشكل شائع بنواة متجانسة مدمجة مُحسَّنة.
  • مُحسِّن الذاكرة - يحلل الرسم البياني لفحص ذروة استخدام الذاكرة لكل عملية ويُدرج عمليات نسخ ذاكرة وحدة المعالجة المركزية ووحدة معالجة الرسومات لمبادلة ذاكرة وحدة معالجة الرسومات إلى وحدة المعالجة المركزية لتقليل ذروة استخدام الذاكرة.
  • مُحسِّن التبعية - يزيل تبعيات التحكم أو يعيد ترتيبها لتقصير المسار الحرج لخطوة نموذج أو لتمكين تحسينات أخرى. يزيل أيضًا العقد التي لا تعمل بشكل فعال مثل Identity.
  • مُحسِّن التقليم - تقليم العقد التي ليس لها أي تأثير على إخراج الرسم البياني. عادةً ما يتم تشغيله أولاً لتقليل حجم الرسم البياني وتسريع المعالجة في ممرات Grappler الأخرى.
  • مُحسِّن الوظائف - يُحسِّن مكتبة الوظائف لبرنامج TensorFlow ويضمن الهيئات الوظيفية لتمكين التحسينات الأخرى بين الإجراءات.
  • مُحسِّن الشكل - يُحسِّن الرسوم البيانية الفرعية التي تعمل على المعلومات ذات الصلة بالشكل والشكل.
  • مُحسِّن موازٍ تلقائي - يوازي الرسوم البيانية تلقائيًا عن طريق الانقسام على طول بُعد الدُفعة. يتم إيقاف تشغيل هذا المحسن افتراضيًا.
  • مُحسِّن الحلقة - يُحسِّن تدفق التحكم في الرسم البياني عن طريق رفع الرسوم البيانية الفرعية غير المتغيرة للحلقة من الحلقات وإزالة عمليات المكدس الزائدة في الحلقات. يُحسِّن أيضًا الحلقات ذات عدد الرحلات المعروفة ثابتًا ويزيل الفروع الميتة المعروفة ثابتًا في الحالات الشرطية.
  • مُحسِّن مخصص النطاق - يقدم مخصصات محددة النطاق لتقليل حركة البيانات ودمج بعض العمليات.
  • التثبيت على مُحسِّن المضيف - يبدل العمليات الصغيرة إلى وحدة المعالجة المركزية. يتم إيقاف تشغيل هذا المحسن افتراضيًا.
  • مُحسِّن الدقة المختلط التلقائي - يحول أنواع البيانات إلى float16 عند الاقتضاء لتحسين الأداء. ينطبق حاليًا على وحدات معالجة الرسومات فقط.
  • متجرد التصحيح - يزيل العُقد المتعلقة بعمليات التصحيح مثل 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

محسن متجرد التصحيح

ضع في اعتبارك دالة بسيطة تتحقق من القيمة الرقمية لوسيطة الإدخال الخاصة بها وتعيدها.

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 .

قم بتمكين مُحسِّن متجرد التصحيح وتنفيذ الوظيفة مرة أخرى.

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)

يزيل مُحسِّن متجرد التصحيح العقدة tf.debug.check_numerics من الرسم البياني وينفذ الوظيفة دون إثارة أي أخطاء.

ملخص

يستخدم وقت تشغيل TensorFlow Grappler لتحسين الرسوم البيانية تلقائيًا قبل التنفيذ. استخدم tf.config.optimizer.set_experimental_options لتمكين أو تعطيل أدوات تحسين الرسم البياني المختلفة.

لمزيد من المعلومات حول Grappler ، راجع تحسينات الرسم البياني TensorFlow .