הצג באתר TensorFlow.org | הפעל בגוגל קולאב | צפה במקור ב-GitHub | הורד מחברת |
קוד tf.keras
ודגמי tf.keras יפעלו בשקיפות על GPU יחיד ללא צורך בשינויי קוד.
הדרך הפשוטה ביותר להפעיל על מספר GPUs, על מחשב אחד או רבים, היא שימוש באסטרטגיות הפצה .
מדריך זה מיועד למשתמשים שניסו את הגישות הללו וגילו שהם צריכים שליטה עדינה על האופן שבו TensorFlow משתמש ב-GPU. כדי ללמוד כיצד לנפות באגים בבעיות ביצועים עבור תרחישים בודדים ומרובי GPU, עיין במדריך אופטימיזציה של TensorFlow GPU Performance .
להכין
ודא שמותקנת אצלך את המהדורה האחרונה של TensorFlow gpu.
import tensorflow as tf
print("Num GPUs Available: ", len(tf.config.list_physical_devices('GPU')))
Num GPUs Available: 1
סקירה כללית
TensorFlow תומך בהפעלת חישובים במגוון סוגי מכשירים, כולל CPU ו-GPU. הם מיוצגים באמצעות מזהי מחרוזת, לדוגמה:
-
"/device:CPU:0"
: המעבד של המחשב שלך. -
"/GPU:0"
: סימון יד קצר עבור ה-GPU הראשון של המחשב שלך הגלוי ל-TensorFlow. -
"/job:localhost/replica:0/task:0/device:GPU:1"
: שם מלא של ה-GPU השני של המחשב שלך הגלוי ל-TensorFlow.
אם לפעולת TensorFlow יש גם מימושי מעבד ו-GPU, כברירת מחדל, התקן ה-GPU מקבל עדיפות כאשר הפעולה מוקצית. לדוגמה, ל- tf.matmul
יש גם גרעיני CPU וגם גרעיני GPU ובמערכת עם התקנים CPU:0
ו- GPU:0
, התקן GPU:0
נבחר להפעיל את tf.matmul
אלא אם תבקש מפורשות להפעיל אותו במכשיר אחר.
אם לפעולת TensorFlow אין יישום GPU תואם, הפעולה נופלת בחזרה להתקן המעבד. לדוגמה, מכיוון tf.cast
יש רק ליבת CPU, במערכת עם התקנים 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
op בוצע ב- 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
בדוגמה זו) ויעתיק אוטומטית טנסורים בין מכשירים במידת הצורך.
הגבלת צמיחת זיכרון GPU
כברירת מחדל, TensorFlow ממפה כמעט את כל זיכרון ה-GPU של כל ה-GPUs (בכפוף ל- CUDA_VISIBLE_DEVICES
) הגלוי לתהליך. זה נעשה כדי להשתמש ביעילות רבה יותר במשאבי זיכרון ה-GPU היקרים יחסית במכשירים על ידי הפחתת פיצול הזיכרון. כדי להגביל את TensorFlow לקבוצה מסוימת של GPUs, השתמש בשיטת 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. הזיכרון אינו משתחרר מכיוון שהוא עלול להוביל לפיצול זיכרון. כדי להפעיל את צמיחת הזיכרון עבור GPU ספציפי, השתמש בקוד הבא לפני הקצאת טנסורים או ביצוע פעולות כלשהן.
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
זה שימושי אם אתה רוצה באמת לאגד את כמות זיכרון ה-GPU הזמינה לתהליך TensorFlow. זהו נוהג מקובל לפיתוח מקומי כאשר ה-GPU משותף עם יישומים אחרים כגון GUI של תחנת עבודה.
שימוש ב-GPU יחיד במערכת מרובת 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
פיתוח עבור מספר GPUs יאפשר למודל להתאים את המשאבים הנוספים. אם מפתחים על מערכת עם GPU יחיד, אתה יכול לדמות מספר GPUs עם מכשירים וירטואליים. זה מאפשר בדיקה קלה של הגדרות ריבוי GPU ללא צורך במשאבים נוספים.
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
ברגע שיש מספר GPUs לוגיים זמינים לזמן הריצה, אתה יכול להשתמש במספר GPUs עם tf.distribute.Strategy
או עם מיקום ידני.
עם tf.distribute.Strategy
השיטה הטובה ביותר לשימוש במספר GPUs היא להשתמש ב- 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
פועל מתחת למכסה המנוע על ידי שכפול חישוב בין מכשירים. אתה יכול ליישם שכפול באופן ידני על ידי בניית המודל שלך על כל GPU. לדוגמה:
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)