วิธีการป้องกันไม่ให้แรงดึงไหลเวียนของการจัดสรรจำนวนรวมของหน่วยความจำ GPU?


282

ฉันทำงานในสภาพแวดล้อมที่ใช้ทรัพยากรการคำนวณร่วมกันนั่นคือเรามีเครื่องเซิร์ฟเวอร์สองสามเครื่องที่มี Nvidia Titan X GPU แต่ละตัว

สำหรับรุ่นขนาดเล็กถึงขนาดกลาง Titan X ขนาด 12 GB นั้นเพียงพอสำหรับผู้ใช้ 2-3 คนในการฝึกอบรมพร้อมกันบน GPU เดียวกัน หากแบบจำลองมีขนาดเล็กพอที่แบบจำลองเดียวไม่ได้ใช้ประโยชน์เต็มที่จากหน่วยคำนวณทั้งหมดของ GPU สิ่งนี้อาจส่งผลให้เกิดการเร่งความเร็วเมื่อเทียบกับกระบวนการฝึกอบรมแบบหนึ่ง แม้ว่าในกรณีที่การเข้าถึง GPU พร้อมกันนั้นทำให้เวลาการฝึกอบรมของแต่ละบุคคลช้าลง แต่ก็ยังดีที่มีความยืดหยุ่นในการมีผู้ใช้หลายคนพร้อมฝึกฝนบน GPU

ปัญหาของ TensorFlow ก็คือโดยปกติแล้วมันจะจัดสรรหน่วยความจำ GPU เต็มจำนวนเมื่อเปิดตัว แม้สำหรับเครือข่ายประสาทสองชั้นขนาดเล็กฉันก็เห็นว่าหน่วยความจำ GPU ทั้งหมด 12 GB หมดลง

มีวิธีในการทำให้ TensorFlow จัดสรรเท่านั้นพูดว่าหน่วยความจำ GPU 4 GB หรือไม่ถ้าใครรู้ว่านี่เพียงพอสำหรับรุ่นที่กำหนดหรือไม่

คำตอบ:


292

คุณสามารถตั้งค่าส่วนของหน่วยความจำ GPU ที่จะจัดสรรเมื่อคุณสร้าง a tf.Sessionโดยส่งผ่านtf.GPUOptionsเป็นส่วนหนึ่งของconfigอาร์กิวเมนต์ตัวเลือก:

# Assume that you have 12GB of GPU memory and want to allocate ~4GB:
gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.333)

sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options))

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


3
ขอบคุณมาก. ข้อมูลนี้ค่อนข้างถูกซ่อนอยู่ในเอกสารปัจจุบัน ฉันจะไม่พบมันด้วยตัวเอง :-) หากคุณสามารถตอบได้ฉันต้องการถามสองข้อมูลเพิ่มเติม: 1- สิ่งนี้ จำกัด จำนวนหน่วยความจำที่เคยใช้หรือเพียงแค่จัดสรรหน่วยความจำในตอนแรกหรือไม่? (เช่นจะยังคงจัดสรรหน่วยความจำเพิ่มหรือไม่หากมีความจำเป็นต้องใช้กราฟการคำนวณ) 2- มีวิธีตั้งค่านี้บนพื้นฐานต่อ GPU หรือไม่?
Fabien C.

15
หมายเหตุที่เกี่ยวข้อง: การตั้งค่า CUDA_VISIBLE_DEVICES เพื่อ จำกัด TensorFlow ให้เป็น GPU ตัวเดียวที่ใช้งานได้สำหรับฉัน ดูacceleware.com/blog/cudavisibledevices-masking-gpus
rd11

2
ดูเหมือนว่าการจัดสรรหน่วยความจำจะค่อนข้างเกินคำขอ e..g ฉันร้องขอ per_process_gpu_memory_fraction = 0.0909 บน 24443MiB gpu และได้รับกระบวนการ 2627MiB
jeremy_rutman

2
ฉันไม่สามารถทำงานนี้ได้ในMonitoredTrainingSession
Anjum Sayed

2
@ jeremy_rutman ฉันเชื่อว่านี่เป็นเพราะการเริ่มต้นบริบท cudnn และ cublas มีความเกี่ยวข้องเฉพาะในกรณีที่คุณเรียกใช้เมล็ดที่ใช้ libs เหล่านั้นเท่านั้น
แดเนียล

187
config = tf.ConfigProto()
config.gpu_options.allow_growth=True
sess = tf.Session(config=config)

https://github.com/tensorflow/tensorflow/issues/1578


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

4
นอกจากนี้ถ้าคุณกำลังใช้ Keras กับแบ็กเอนด์ TF, คุณสามารถใช้และเรียกใช้from keras import backend as KและK.set_session(sess)ข้อ จำกัด ของหน่วยความจำที่หลีกเลี่ยง
โอลิเวอร์

50

นี่คือข้อความที่ตัดตอนมาจากหนังสือ Deep Learning with TensorFlow

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

1) อนุญาตการเติบโต: (ยืดหยุ่นมากขึ้น)

config = tf.ConfigProto()
config.gpu_options.allow_growth = True
session = tf.Session(config=config, ...)

วิธีที่สองคือper_process_gpu_memory_fractionตัวเลือกซึ่งกำหนดสัดส่วนของจำนวนหน่วยความจำโดยรวมที่eachควรจัดสรร GPU ที่มองเห็นได้ หมายเหตุ:ไม่จำเป็นต้องมีการเปิดตัวหน่วยความจำมันสามารถทำให้การกระจายตัวของหน่วยความจำแย่ลงเมื่อดำเนินการเสร็จ

2) จัดสรรหน่วยความจำคงที่ :

หากต้องการจัดสรร40%หน่วยความจำทั้งหมดของ GPU แต่ละตัวโดย:

config = tf.ConfigProto()
config.gpu_options.per_process_gpu_memory_fraction = 0.4
session = tf.Session(config=config, ...)

หมายเหตุ: มีประโยชน์เฉพาะถ้าคุณต้องการผูกจำนวนหน่วยความจำ GPU ที่มีอยู่ในกระบวนการ TensorFlow อย่างแท้จริง


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

25

อัปเดตสำหรับ TensorFlow 2.0 Alpha และสูงกว่า

จาก 2.0 Alpha docs ตอนนี้คำตอบก็แค่หนึ่งบรรทัดก่อนที่คุณจะทำอะไรกับ TensorFlow:

import tensorflow as tf
tf.config.gpu.set_per_process_memory_growth(True)

1
@AkshayLAradhya ไม่ได้มีไว้สำหรับ TF 2.0 ขึ้นไป คำตอบอื่น ๆ ที่นี่จะทำงานได้ดีสำหรับ 1.13 และก่อนหน้านี้
Theo

19

คำตอบทั้งหมดข้างต้นถือว่าเป็นการดำเนินการด้วยการsess.run()โทรซึ่งกำลังกลายเป็นข้อยกเว้นมากกว่ากฎใน TensorFlow เวอร์ชันล่าสุด

เมื่อใช้tf.Estimatorเฟรมเวิร์ก (TensorFlow 1.4 และสูงกว่า) วิธีการส่งผ่านเศษส่วนไปยังส่วนที่สร้างขึ้นโดยนัยMonitoredTrainingSessionคือ

opts = tf.GPUOptions(per_process_gpu_memory_fraction=0.333)
conf = tf.ConfigProto(gpu_options=opts)
trainingConfig = tf.estimator.RunConfig(session_config=conf, ...)
tf.estimator.Estimator(model_fn=..., 
                       config=trainingConfig)

ในทำนองเดียวกันในโหมด Eager (TensorFlow 1.5 ขึ้นไป)

opts = tf.GPUOptions(per_process_gpu_memory_fraction=0.333)
conf = tf.ConfigProto(gpu_options=opts)
tfe.enable_eager_execution(config=conf)

แก้ไข: 11-04-2018 เป็นตัวอย่างถ้าคุณต้องการใช้tf.contrib.gan.trainคุณสามารถใช้บางสิ่งที่คล้ายกับการร้อง:

tf.contrib.gan.gan_train(........, config=conf)

16

สำหรับ Tensorflow เวอร์ชัน 2.0 และ 2.1 ให้ใช้ข้อมูลโค้ดต่อไปนี้ :

 import tensorflow as tf
 gpu_devices = tf.config.experimental.list_physical_devices('GPU')
 tf.config.experimental.set_memory_growth(gpu_devices[0], True)

สำหรับรุ่นก่อนหน้าตัวอย่างต่อไปนี้ใช้สำหรับฉัน:

import tensorflow as tf
tf_config=tf.ConfigProto()
tf_config.gpu_options.allow_growth=True
sess = tf.Session(config=tf_config)

10

Tensorflow 2.0 Beta และ (อาจ) เกินกว่านั้น

API เปลี่ยนแปลงอีกครั้ง สามารถพบได้ใน:

tf.config.experimental.set_memory_growth(
    device,
    enable
)

นามแฝง:

  • tf.compat.v1.config.experimental.set_memory_growth
  • tf.compat.v2.config.experimental.set_memory_growth

อ้างอิง:

ดูเพิ่มเติมที่: Tensorflow - ใช้ GPU : https://www.tensorflow.org/guide/gpu

สำหรับ Tensorflow 2.0 Alpha โปรดดู: คำตอบนี้


9

คุณสามารถใช้ได้

TF_FORCE_GPU_ALLOW_GROWTH=true

ในตัวแปรสภาพแวดล้อมของคุณ

ในรหัสtensorflow :

bool GPUBFCAllocator::GetAllowGrowthValue(const GPUOptions& gpu_options) {
  const char* force_allow_growth_string =
      std::getenv("TF_FORCE_GPU_ALLOW_GROWTH");
  if (force_allow_growth_string == nullptr) {
    return gpu_options.allow_growth();
}

5

ปลั๊กไร้ยางอาย: หากคุณติดตั้ง GPU ที่รองรับ Tensorflow เซสชันจะจัดสรร GPU ทั้งหมดก่อนไม่ว่าคุณจะตั้งค่าให้ใช้เฉพาะ CPU หรือ GPU ฉันอาจเพิ่มเคล็ดลับของฉันที่แม้คุณตั้งค่ากราฟให้ใช้ CPU เท่านั้นคุณควรตั้งค่าการตั้งค่าเดียวกัน (ตามคำตอบข้างต้น :)) เพื่อป้องกันการยึดครอง GPU ที่ไม่พึงประสงค์

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


3

สำหรับTensorflow 2.0นี้การแก้ปัญหานี้ทำงานให้ฉัน (TF-GPU 2.0, Windows 10, GeForce RTX 2070)

physical_devices = tf.config.experimental.list_physical_devices('GPU')
assert len(physical_devices) > 0, "Not enough GPU hardware devices available"
tf.config.experimental.set_memory_growth(physical_devices[0], True)

1
ฉันใช้ TF-GPU 2.0, Ubuntu 16.04.6, Tesla K80
azar

@azar - ขอบคุณสำหรับการแบ่งปัน นั่นเป็นเรื่องที่น่าสนใจเหมือนกันทั้งใน Ubuntu และ Windows อย่างใดฉันมักจะคิดว่าปัญหาจะแตกต่างกันเมื่อเข้าใกล้ฮาร์ดแวร์ บางทีนี่อาจน้อยลงเมื่อเวลาผ่านไป - อาจเป็นเรื่องดี
Sunsetquest

3

หากคุณใช้ Tensorflow 2 ให้ลองปฏิบัติดังนี้:

config = tf.compat.v1.ConfigProto()
config.gpu_options.allow_growth = True
session = tf.compat.v1.Session(config=config)

ทำงานให้กับ Tensorflow 2
mobin alhassan

1

ฉันพยายามฝึกฝน unet ในชุดข้อมูล Voc แต่เนื่องจากขนาดภาพใหญ่หน่วยความจำจึงเสร็จสิ้น ฉันลองใช้เคล็ดลับข้างต้นทั้งหมดแล้วลองใช้กับชุดขนาด == 1 แต่ก็ยังไม่ปรับปรุง บางครั้งรุ่น TensorFlow ยังทำให้เกิดปัญหาหน่วยความจำ ลองโดยใช้

pip install tensorflow-gpu == 1.8.0


1

ฉันใหม่กับ tensorflow ฉันมี Geforce 740m หรือบางสิ่งบางอย่างกับ GPU 2GB RAM ฉันกำลังใช้ตัวอย่างแบบ mnist ที่เขียนด้วยลายมือสำหรับภาษาพื้นเมืองที่มีข้อมูลการฝึกอบรมที่มี 38700 ภาพและ 4300 ภาพทดสอบและพยายามที่จะแม่นยำเรียกคืน F1 ใช้รหัสต่อไปนี้เนื่องจาก sklearn ไม่ได้ให้รีบูตฉันอย่างแม่นยำ เมื่อฉันเพิ่มลงในรหัสที่มีอยู่ของฉันฉันเริ่มรับข้อผิดพลาด GPU

TP = tf.count_nonzero(predicted * actual)
TN = tf.count_nonzero((predicted - 1) * (actual - 1))
FP = tf.count_nonzero(predicted * (actual - 1))
FN = tf.count_nonzero((predicted - 1) * actual)

prec = TP / (TP + FP)
recall = TP / (TP + FN)
f1 = 2 * prec * recall / (prec + recall)

บวกกับแบบจำลองของฉันหนักฉันเดาฉันได้รับข้อผิดพลาดของหน่วยความจำหลังจาก 147, 148 epochs และจากนั้นฉันคิดว่าทำไมไม่สร้างฟังก์ชั่นสำหรับงานดังนั้นฉันไม่รู้ว่ามันทำงานในโหมดนี้หรือไม่ ใช้และเมื่ออยู่นอกขอบเขตอาจปล่อยหน่วยความจำและฉันกำหนดองค์ประกอบข้างต้นสำหรับการฝึกอบรมและการทดสอบในโมดูลฉันสามารถบรรลุ 10,000 epochs โดยไม่มีปัญหาใด ๆ ฉันหวังว่าสิ่งนี้จะช่วย ..


ฉันประหลาดใจที่ยูทิลิตี้ของ TF แต่ด้วยการใช้หน่วยความจำ บน CPU หลามจัดสรร 30GB หรือมากกว่านั้นสำหรับงานฝึกอบรมบนชุดข้อมูลดอกไม้ที่ใช้ในอาจ TF ตัวอย่าง บ้า.
Eric M

1
# allocate 60% of GPU memory 
from keras.backend.tensorflow_backend import set_session
import tensorflow as tf 
config = tf.ConfigProto()
config.gpu_options.per_process_gpu_memory_fraction = 0.6
set_session(tf.Session(config=config))

คำตอบที่ให้ถูกตั้งค่าสถานะเพื่อตรวจสอบว่าโพสต์คุณภาพต่ำ นี่เป็นแนวทางสำหรับฉันจะเขียนคำตอบที่ดีได้อย่างไร . คำตอบที่ให้นี้อาจถูกต้อง แต่อาจได้ประโยชน์จากคำอธิบาย คำตอบของรหัสเท่านั้นจะไม่ถือว่าคำตอบ "ดี" จากการตรวจสอบ
เทรนตัน McKinney
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.