cada blog, cada lema: puedes hacer más de lo que crees.
0. Prefacio
Esta sección explica principalmente la configuración de la GPU. Específicamente, cómo ahorrar recursos de GPU. No hay mucho que decir, veamos el tema principal a continuación:
1. Texto
1.1 Introducción
- tensorflow llenará la GPU (tanto como sea posible) de forma predeterminada, lo que hará que otros programas no puedan usar la GPU, lo que resultará en un desperdicio de memoria y recursos informáticos de la GPU. Por lo general, existen los siguientes métodos:
- Establecer el crecimiento personal de la memoria
- Mecanismo de dispositivo virtual (similar a un disco de ventana)
- Uso de múltiples GPU
- GPU virtual y GPU real
- Configuración manual y mecanismo distribuido
Descripción de la lista de API : el comentario está debajo del código correspondiente
tf.debugging.set_log_device_placement
# 打印变量在哪个设备上
tf.config.experimental.set_visible_devices
# 设置对本进程可见的设备
tf.config.experimental.list_logical_devices
# 获取所有的逻辑设备
tf.config.experimental.list_physical_devices
# 获取物理设备的列表
tf.config.experimental.set_memory_growth
# 设置内存自增长
tf.config.experimental.VirtualDeviceConfiguration
# 建立逻辑分区
tf.config.set_soft_device_placement
# 自动分配变量到某个设备上
- Supervisar las condiciones de la GPU
- General
Ingrese en la consola de la ventana (win + R -> cmd) o en la terminal de Linux
nvidia-smi
Ventana de monitoreo en tiempo real
nvidi-smi -l
linux (ubuntu):
watch -n 0.1 nvidia-smi
1.2 Establecer el crecimiento personal de la memoria
De forma predeterminada, el programa tendrá la memoria de la GPU (como) al máximo, aunque no usó tanta memoria, como se muestra a continuación:
Al comienzo de la posición del programa , configure la memoria desde el crecimiento, de la siguiente manera:
Nota: En Al comienzo del programa, configure el crecimiento propio de la memoria para la GPU y llame a la siguiente función.
def set_GPU():
"""GPU相关设置"""
# 打印变量在那个设备上
# tf.debugging.set_log_device_placement(True)
# 获取物理GPU个数
gpus = tf.config.experimental.list_physical_devices('GPU')
print('物理GPU个数为:', len(gpus))
# 设置内存自增长
for gpu in gpus:
tf.config.experimental.set_memory_growth(gpu, True)
print('-------------已设置完GPU内存自增长--------------')
# 获取逻辑GPU个数
logical_gpus = tf.config.experimental.list_logical_devices('GPU')
print('逻辑GPU个数为:', len(logical_gpus))
El uso de la GPU es el siguiente:
1.3 Especificar la GPU para que sea visible
Por defecto, el programa usará la primera GPU, podemos especificarlo, es decir, dejar que el programa se ejecute en la GPU que especifiquemos. el código se muestra a continuación:
def set_GPU():
"""GPU相关设置"""
# 打印变量在那个设备上
# tf.debugging.set_log_device_placement(True)
# 获取物理GPU个数
gpus = tf.config.experimental.list_physical_devices('GPU')
print('物理GPU个数为:', len(gpus))
# 设置内存自增长
for gpu in gpus:
tf.config.experimental.set_memory_growth(gpu, True)
print('-------------已设置完GPU内存自增长--------------')
# 设置哪个GPU对设备可见,即指定用哪个GPU
tf.config.experimental.set_visible_devices(gpus[-1], 'GPU')
# 获取逻辑GPU个数
logical_gpus = tf.config.experimental.list_logical_devices('GPU')
print('逻辑GPU个数为:', len(logical_gpus))
Descripción:
- La máquina tiene solo 1 GPU, por lo que el programa se ejecuta en el servidor, por lo que la información de nvidia es ligeramente diferente.
- Como se muestra en el código, especificamos que la última GPU es visible, es decir, usamos la última GPU.
- Todavía hay dos GPU físicas y ahora solo hay una GPU lógica.
- Entre ellos, todavía establecemos el crecimiento personal de la memoria.
1.4 segmentación de GPU
Descripción:
- Similar a dividir un disco físico en varias zonas, es decir, cuando usamos habitualmente la computadora, puede que solo haya un disco físico en la computadora, pero lo dividiremos en varias zonas, como la unidad C, la unidad D, etc.
- GPU física, es decir, una GPU real; GPU lógica, es decir, GPU virtual (mapeo de GPU física a GPU lógica)
def set_GPU():
"""GPU相关设置"""
# 打印变量在那个设备上
# tf.debugging.set_log_device_placement(True)
# 获取物理GPU个数
gpus = tf.config.experimental.list_physical_devices('GPU')
print('物理GPU个数为:', len(gpus))
# 设置内存自增长
# for gpu in gpus:
# tf.config.experimental.set_memory_growth(gpu, True)
# print('-------------已设置完GPU内存自增长--------------')
# 设置哪个GPU对设备可见,即指定用哪个GPU
tf.config.experimental.set_visible_devices(gpus[-1], 'GPU')
# 切分逻辑GPU
tf.config.experimental.set_virtual_device_configuration(
gpus[-1], # 指定要切割的物理GPU
# 切割的个数,和每块逻辑GPU的大小
[tf.config.experimental.VirtualDeviceConfiguration(memory_limit=4096),
tf.config.experimental.VirtualDeviceConfiguration(memory_limit=4096), ]
)
# 获取逻辑GPU个数
logical_gpus = tf.config.experimental.list_logical_devices('GPU')
print('逻辑GPU个数为:', len(logical_gpus))
Como se muestra en la figura siguiente, decimos que la última GPU física está dividida en dos partes. Ahora el número de GPU lógicas es 2, que es diferente de la GPU lógica de 1 en (1.2) anterior.
1.5 Uso de un entorno multi-GPU
1.5.1 Especificar manualmente
el código se muestra a continuación:
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
import tensorflow as tf
gpus = tf.config.experimental.list_physical_devices('GPU')
print('物理GPU个数为:', len(gpus))
# 设置内存自增长
for gpu in gpus:
tf.config.experimental.set_memory_growth(gpu, True)
print('-------------已设置完GPU内存自增长--------------')
# 获取逻辑GPU个数
logical_gpus = tf.config.experimental.list_logical_devices('GPU')
print('逻辑GPU个数为:', len(logical_gpus))
c = []
# 手动指定多GPU环境
for gpu in logical_gpus:
print(gpu.name)
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)
dañar:
- Demasiados detalles para controlar
- Algunos dispositivos no son compatibles
1.5.2 Estrategia distribuida
1. Estrategia reflejada
- Entrenamiento distribuido sincrónico
- Adecuado para una máquina con varias tarjetas
- Cada GPU tiene todos los parámetros de la estructura de la red, estos parámetros se sincronizarán
- Paralelo de datos
- Los datos por lotes se cortan en N copias en cada GPU
- Luego, la agregación de gradientes se actualiza a los parámetros de cada GPU
2. CentralStorageStrategy
- Variante de MirroredStrategy
- Los parámetros no se almacenan en cada GPU, sino que se almacenan en un dispositivo
- CPU o solo GPU
- El cálculo es paralelo en todas las GPU
- Además del cálculo de los parámetros de actualización
3. MultiWorkerMirroredStrategy
- Similar a MirroredStrategy
- Adecuado para situaciones de múltiples máquinas y tarjetas
4. TPUStrategy
- Similar a MirroredStrategy
- Usa la estrategia en TPU
4. ParameterServerStrategy
- Distribuido asincrónico
- Más adecuado para sistemas distribuidos
- La máquina se divide en dos categorías: servidor de parámetros y trabajador
- El servidor de parámetros es responsable de integrar gradientes y actualizar parámetros
- El trabajador es responsable de la informática y la formación de la red.
Los pros y los contras de la sincronización y la asincronía
- Multitarjeta multimáquina
- La asincronía puede evitar efectos de tabla corta
- Una máquina con varias tarjetas
- La sincronización puede evitar una comunicación excesiva
- Los cálculos asincrónicos aumentarán el alcance del modelo
- La asincronía no es estrictamente correcta, por lo que el modelo es más fácil de tolerar errores.
1.6 Resumen
Formas de ahorrar recursos de memoria de la GPU:
- Crecimiento propio
- Segmentación lógica
referencias
[1] https://blog.csdn.net/weixin_39190382/article/details/104739572