مساعدة في حماية الحاجز المرجاني العظيم مع TensorFlow على Kaggle تاريخ التحدي

استخدم GPU

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

كود TensorFlow، و tf.keras ستستمر نماذج بشفافية على GPU واحد مع أي تغييرات رمز المطلوبة.

إن أبسط طريقة لتشغيل على وحدات معالجة الرسومات المتعددة، على واحد أو العديد من الأجهزة، واستخدام استراتيجيات التوزيع .

هذا الدليل مخصص للمستخدمين الذين جربوا هذه الأساليب ووجدوا أنهم بحاجة إلى تحكم دقيق في كيفية استخدام TensorFlow لوحدة معالجة الرسومات. لمعرفة كيفية تصحيح مشاكل الأداء لسيناريوهات واحدة ومتعددة GPU، راجع و تحسين TensorFlow GPU الأداء دليل.

اقامة

تأكد من تثبيت أحدث إصدار gpu من TensorFlow.

import tensorflow as tf
print("Num GPUs Available: ", len(tf.config.list_physical_devices('GPU')))
Num GPUs Available:  1

ملخص

يدعم TensorFlow العمليات الحسابية الجارية على مجموعة متنوعة من الأجهزة ، بما في ذلك وحدة المعالجة المركزية ووحدة معالجة الرسومات. يتم تمثيلها بمعرفات السلسلة على سبيل المثال:

  • "/device:CPU:0" : وحدة المعالجة المركزية من جهازك.
  • "/GPU:0" : تدوين القصير اليد للGPU الأول من جهازك مرئيا لTensorFlow.
  • "/job:localhost/replica:0/task:0/device:GPU:1" : اسم مؤهل بالكامل من GPU الثاني من جهازك مرئيا لTensorFlow.

إذا كانت عملية TensorFlow تشتمل على تطبيقات CPU و GPU ، فسيتم منح الأولوية لجهاز GPU بشكل افتراضي عند تعيين العملية. على سبيل المثال، tf.matmul على حد سواء وحدة المعالجة المركزية والجرافيك حبات وعلى نظام مع الأجهزة CPU:0 و GPU:0 ، و GPU:0 تحديد جهاز لتشغيل tf.matmul إلا إذا طلب صراحة لتشغيله على جهاز آخر.

إذا لم يكن لعملية TensorFlow تنفيذ GPU مطابق ، فإن العملية تعود إلى جهاز وحدة المعالجة المركزية. على سبيل المثال، منذ tf.cast ليس لديها سوى نواة وحدة المعالجة المركزية، على نظام مع الأجهزة CPU:0 و GPU:0 و CPU:0 تحديد الجهاز لتشغيل tf.cast ، حتى لو طلب لتشغيل على GPU:0 الجهاز .

وضع جهاز التسجيل

لمعرفة الأجهزة التي تم تعيينها العمليات والتنسورات ل، وضع tf.debugging.set_log_device_placement(True) كما في البيان الأول من البرنامج. يؤدي تمكين تسجيل وضع الجهاز إلى طباعة أي عمليات تخصيص أو عمليات Tensor.

tf.debugging.set_log_device_placement(True)

# Create some tensors
a = tf.constant([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
b = tf.constant([[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]])
c = tf.matmul(a, b)

print(c)
Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op MatMul in device /job:localhost/replica:0/task:0/device:GPU:0
tf.Tensor(
[[22. 28.]
 [49. 64.]], shape=(2, 2), dtype=float32)

سوف رمز أعلاه طباعة مؤشرا على MatMul أعدم المرجع على GPU:0 .

وضع الجهاز اليدوي

إذا كنت ترغب في الحصول على عملية معينة لتشغيلها على جهاز من اختيارك بدلا من ما تلقائيا لك، يمكنك استخدام with tf.device لخلق سياق الجهاز، وجميع العمليات في هذا السياق تشغيل على الجهاز المعين نفسه .

tf.debugging.set_log_device_placement(True)

# Place tensors on the CPU
with tf.device('/CPU:0'):
  a = tf.constant([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
  b = tf.constant([[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]])

# Run on the GPU
c = tf.matmul(a, b)
print(c)
Executing op MatMul in device /job:localhost/replica:0/task:0/device:GPU:0
tf.Tensor(
[[22. 28.]
 [49. 64.]], shape=(2, 2), dtype=float32)

سترى أن الآن a و b تم تعيينها إلى CPU:0 . منذ لم يتم تحديد جهاز صراحة على MatMul العملية، فإن وقت التشغيل TensorFlow اختيار واحد على أساس التشغيل والأجهزة المتوفرة ( GPU:0 في هذا المثال) وتلقائيا نسخ التنسورات بين الأجهزة إذا لزم الأمر.

الحد من نمو ذاكرة وحدة معالجة الرسومات

افتراضيا، خرائط TensorFlow ما يقرب من جميع من ذاكرة GPU من جميع وحدات معالجة الرسومات (رهنا CUDA_VISIBLE_DEVICES ) مرئية للعملية. يتم ذلك لزيادة كفاءة استخدام موارد ذاكرة وحدة معالجة الرسومات الثمينة نسبيًا على الأجهزة عن طريق تقليل تجزئة الذاكرة. للحد من TensorFlow إلى مجموعة محددة من وحدات معالجة الرسومات، استخدم tf.config.set_visible_devices الأسلوب.

gpus = tf.config.list_physical_devices('GPU')
if gpus:
  # Restrict TensorFlow to only use the first GPU
  try:
    tf.config.set_visible_devices(gpus[0], 'GPU')
    logical_gpus = tf.config.list_logical_devices('GPU')
    print(len(gpus), "Physical GPUs,", len(logical_gpus), "Logical GPU")
  except RuntimeError as e:
    # Visible devices must be set before GPUs have been initialized
    print(e)
1 Physical GPUs, 1 Logical GPU

في بعض الحالات ، يكون من المستحسن أن تقوم العملية بتخصيص مجموعة فرعية فقط من الذاكرة المتاحة ، أو زيادة استخدام الذاكرة فقط كما هو مطلوب من قبل العملية. يوفر TensorFlow طريقتين للتحكم في ذلك.

الخيار الأول هو بدوره على نمو الذاكرة من خلال الدعوة tf.config.experimental.set_memory_growth ، الذي محاولات لتخصيص فقط كما الكثير من الذاكرة GPU حسب الحاجة لتخصيص وقت التشغيل: ويبدأ من تخصيص الذاكرة قليلة جدا، وكما يحصل تشغيل البرنامج و هناك حاجة إلى المزيد من ذاكرة GPU ، يتم تمديد منطقة ذاكرة GPU لعملية TensorFlow. لا يتم تحرير الذاكرة لأنها يمكن أن تؤدي إلى تجزئة الذاكرة. لتشغيل نمو الذاكرة لوحدة معالجة رسومات معينة ، استخدم الكود التالي قبل تخصيص أي موتر أو تنفيذ أي عمليات.

gpus = tf.config.list_physical_devices('GPU')
if gpus:
  try:
    # Currently, memory growth needs to be the same across GPUs
    for gpu in gpus:
      tf.config.experimental.set_memory_growth(gpu, True)
    logical_gpus = tf.config.list_logical_devices('GPU')
    print(len(gpus), "Physical GPUs,", len(logical_gpus), "Logical GPUs")
  except RuntimeError as e:
    # Memory growth must be set before GPUs have been initialized
    print(e)
Physical devices cannot be modified after being initialized

وهناك طريقة أخرى لتمكين هذا الخيار هو تعيين متغير البيئة TF_FORCE_GPU_ALLOW_GROWTH إلى true . هذا التكوين هو منصة محددة.

الطريقة الثانية هي لتكوين جهاز GPU الظاهري مع tf.config.set_logical_device_configuration ووضع حد الثابت على الذاكرة الإجمالية للتخصيص على GPU.

gpus = tf.config.list_physical_devices('GPU')
if gpus:
  # Restrict TensorFlow to only allocate 1GB of memory on the first GPU
  try:
    tf.config.set_logical_device_configuration(
        gpus[0],
        [tf.config.LogicalDeviceConfiguration(memory_limit=1024)])
    logical_gpus = tf.config.list_logical_devices('GPU')
    print(len(gpus), "Physical GPUs,", len(logical_gpus), "Logical GPUs")
  except RuntimeError as e:
    # Virtual devices must be set before GPUs have been initialized
    print(e)
Virtual devices cannot be modified after being initialized

يكون هذا مفيدًا إذا كنت تريد حقًا ربط مقدار ذاكرة وحدة معالجة الرسومات المتاحة لعملية TensorFlow. هذه ممارسة شائعة للتطوير المحلي عندما تتم مشاركة GPU مع تطبيقات أخرى مثل واجهة المستخدم الرسومية لمحطة العمل.

استخدام وحدة معالجة رسومات واحدة على نظام متعدد GPU

إذا كان لديك أكثر من GPU في نظامك ، فسيتم تحديد GPU مع أدنى معرف افتراضيًا. إذا كنت ترغب في العمل على وحدة معالجة رسومات مختلفة ، فستحتاج إلى تحديد التفضيل بشكل صريح:

tf.debugging.set_log_device_placement(True)

try:
  # Specify an invalid GPU device
  with tf.device('/device:GPU:2'):
    a = tf.constant([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
    b = tf.constant([[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]])
    c = tf.matmul(a, b)
except RuntimeError as e:
  print(e)
Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op MatMul in device /job:localhost/replica:0/task:0/device:GPU:0

إذا كان الجهاز الذي حددته غير موجود، سوف تحصل على RuntimeError : .../device:GPU:2 unknown device .

إذا كنت ترغب TensorFlow لاختيار الجهاز الموجود ودعم لتشغيل العمليات في حالة تحديد واحد غير موجود تلقائيا، يمكنك الاتصال tf.config.set_soft_device_placement(True) .

tf.config.set_soft_device_placement(True)
tf.debugging.set_log_device_placement(True)

# Creates some tensors
a = tf.constant([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
b = tf.constant([[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]])
c = tf.matmul(a, b)

print(c)
Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op MatMul in device /job:localhost/replica:0/task:0/device:GPU:0
tf.Tensor(
[[22. 28.]
 [49. 64.]], shape=(2, 2), dtype=float32)

استخدام العديد من وحدات معالجة الرسومات

سيسمح التطوير لوحدات معالجة الرسومات المتعددة للنموذج بالتوسع مع الموارد الإضافية. في حالة التطوير على نظام به وحدة معالجة رسومات واحدة ، يمكنك محاكاة وحدات معالجة رسومات متعددة باستخدام أجهزة افتراضية. يتيح هذا الاختبار السهل لإعدادات وحدات معالجة الرسومات المتعددة دون الحاجة إلى موارد إضافية.

gpus = tf.config.list_physical_devices('GPU')
if gpus:
  # Create 2 virtual GPUs with 1GB memory each
  try:
    tf.config.set_logical_device_configuration(
        gpus[0],
        [tf.config.LogicalDeviceConfiguration(memory_limit=1024),
         tf.config.LogicalDeviceConfiguration(memory_limit=1024)])
    logical_gpus = tf.config.list_logical_devices('GPU')
    print(len(gpus), "Physical GPU,", len(logical_gpus), "Logical GPUs")
  except RuntimeError as e:
    # Virtual devices must be set before GPUs have been initialized
    print(e)
Virtual devices cannot be modified after being initialized

مرة واحدة هناك عدة وحدات معالجة الرسومات المنطقية المتاحة للوقت، يمكنك الاستفادة من وحدات معالجة الرسومات المتعددة مع tf.distribute.Strategy أو مع وضع اليدوي.

مع tf.distribute.Strategy

أفضل الممارسات لاستخدام وحدات معالجة الرسومات المتعددة لاستخدام tf.distribute.Strategy . اليك مثال بسيط:

tf.debugging.set_log_device_placement(True)
gpus = tf.config.list_logical_devices('GPU')
strategy = tf.distribute.MirroredStrategy(gpus)
with strategy.scope():
  inputs = tf.keras.layers.Input(shape=(1,))
  predictions = tf.keras.layers.Dense(1)(inputs)
  model = tf.keras.models.Model(inputs=inputs, outputs=predictions)
  model.compile(loss='mse',
                optimizer=tf.keras.optimizers.SGD(learning_rate=0.2))
Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op VarHandleOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op AssignVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
INFO:tensorflow:Using MirroredStrategy with devices ('/job:localhost/replica:0/task:0/device:GPU:0',)
Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op RandomUniform in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op Sub in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op Mul in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op AddV2 in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op VarHandleOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op AssignVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op NoOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op ReadVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op Identity in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op ReadVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op Identity in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op Fill in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op VarHandleOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op AssignVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op NoOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op ReadVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op Identity in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op ReadVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op Identity in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op VarHandleOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op AssignVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op NoOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op VarHandleOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op AssignVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op NoOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op VarHandleOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op AssignVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op NoOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op Fill in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op VarHandleOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op AssignVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op NoOp in device /job:localhost/replica:0/task:0/device:GPU:0
INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:CPU:0 then broadcast to ('/job:localhost/replica:0/task:0/device:CPU:0',).
Executing op ReadVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op Identity in device /job:localhost/replica:0/task:0/device:CPU:0
INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:CPU:0 then broadcast to ('/job:localhost/replica:0/task:0/device:CPU:0',).
Executing op ReadVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op Identity in device /job:localhost/replica:0/task:0/device:CPU:0
Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op Fill in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op VarHandleOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op AssignVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op NoOp in device /job:localhost/replica:0/task:0/device:GPU:0
INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:CPU:0 then broadcast to ('/job:localhost/replica:0/task:0/device:CPU:0',).
Executing op ReadVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op Identity in device /job:localhost/replica:0/task:0/device:CPU:0
INFO:tensorflow:Reduce to /job:localhost/replica:0/task:0/device:CPU:0 then broadcast to ('/job:localhost/replica:0/task:0/device:CPU:0',).
Executing op ReadVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op Identity in device /job:localhost/replica:0/task:0/device:CPU:0
Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op VarHandleOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op AssignVariableOp in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op NoOp in device /job:localhost/replica:0/task:0/device:GPU:0

سيتم تشغيل هذا البرنامج نسخة من النموذج الخاص بك على كل GPU، وتقسيم إدخال البيانات بينهما، المعروف أيضا باسم " التوازي البيانات ".

لمزيد من المعلومات حول استراتيجيات التوزيع، تحقق من دليل هنا .

التنسيب اليدوي

tf.distribute.Strategy يعمل تحت غطاء محرك السيارة عن طريق تكرار الحساب عبر الأجهزة. يمكنك تنفيذ النسخ المتماثل يدويًا عن طريق إنشاء النموذج الخاص بك على كل وحدة معالجة رسومات. على سبيل المثال:

tf.debugging.set_log_device_placement(True)

gpus = tf.config.list_logical_devices('GPU')
if gpus:
  # Replicate your computation on multiple GPUs
  c = []
  for gpu in gpus:
    with tf.device(gpu.name):
      a = tf.constant([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
      b = tf.constant([[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]])
      c.append(tf.matmul(a, b))

  with tf.device('/CPU:0'):
    matmul_sum = tf.add_n(c)

  print(matmul_sum)
Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op _EagerConst in device /job:localhost/replica:0/task:0/device:GPU:0
Executing op MatMul in device /job:localhost/replica:0/task:0/device:GPU:0
tf.Tensor(
[[22. 28.]
 [49. 64.]], shape=(2, 2), dtype=float32)