Флаг backends.cudnn.deterministic
Флаг torch.backends.cudnn.deterministic управляет детерминизмом
вычислений в библиотеке cuDNN. Когда флаг установлен в True,
cuDNN выбирает только детерминированные алгоритмы для свёрточных
и других операций, что гарантирует воспроизводимость результатов
при одинаковых входных данных и начальном состоянии. Однако это
может снизить производительность, так как некоторые оптимизированные
недетерминированные алгоритмы становятся недоступны. По умолчанию
флаг имеет значение False.
Синтаксис
torch.backends.cudnn.deterministic = True
# или
torch.backends.cudnn.deterministic = False
Пример
Давайте установим флаг в детерминированный режим и выполним свёрточную операцию:
import torch
torch.manual_seed(0)
torch.backends.cudnn.deterministic = True
# Создаём входной тензор и слой свёртки
x = torch.randn(1, 3, 32, 32, device='cuda')
conv = torch.nn.Conv2d(3, 16, kernel_size=3, padding=1).cuda()
# Выполняем свёртку дважды
res1 = conv(x)
res2 = conv(x)
# Проверяем идентичность результатов
print(torch.allclose(res1, res2))
Результат выполнения кода:
True
Пример
Сравним детерминированный и недетерминированный режимы
с использованием cudnn.benchmark, который также
влияет на выбор алгоритмов:
import torch
torch.manual_seed(0)
# Включаем детерминированный режим
torch.backends.cudnn.deterministic = True
torch.backends.cudnn.benchmark = False
x = torch.randn(1, 3, 32, 32, device='cuda')
conv = torch.nn.Conv2d(3, 16, kernel_size=3, padding=1).cuda()
res1 = conv(x)
res2 = conv(x)
print("Детерминированный режим:", torch.allclose(res1, res2))
# Отключаем детерминированный режим
torch.backends.cudnn.deterministic = False
torch.backends.cudnn.benchmark = True
# Сбрасываем состояние для чистоты эксперимента
torch.manual_seed(0)
res1 = conv(x)
res2 = conv(x)
print("Недетерминированный режим:", torch.allclose(res1, res2))
Результат выполнения кода:
"Детерминированный режим: True"
"Недетерминированный режим: True"
Обратите внимание, что даже в недетерминированном режиме при одинаковых входных данных результаты могут совпадать, так как cuDNN выбирает алгоритм один раз. Однако при разных размерах входных данных или архитектурах воспроизводимость не гарантируется.
Пример
Покажем влияние флага на обучение модели, выполняя два запуска с одинаковым начальным состоянием:
import torch
def train_model():
torch.manual_seed(42)
torch.backends.cudnn.deterministic = True
model = torch.nn.Linear(10, 1).cuda()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
x = torch.randn(4, 10, device='cuda')
y = torch.randn(4, 1, device='cuda')
for _ in range(3):
optimizer.zero_grad()
output = model(x)
loss = torch.nn.functional.mse_loss(output, y)
loss.backward()
optimizer.step()
return model.weight.data.clone()
# Запускаем обучение дважды
weights1 = train_model()
weights2 = train_model()
print(torch.allclose(weights1, weights2))
Результат выполнения кода:
True
Смотрите также
-
флаг
cudnn.benchmark,
который автоматически выбирает оптимальные алгоритмы cuDNN -
флаг
cudnn.allow_tf32,
который включает использование TF32 на GPU с поддержкой -
функцию
is_available,
которая проверяет доступность CUDA-устройств -
функцию
device_count,
которая возвращает количество доступных GPU