Хорошо, пока я нашел обходной путь. Моя гипотеза была верна, если подсистема PyTorch CUDA уже инициализирована до того, как дочерний процесс разветвлен, установка CUDA_VISIBLE_DEVICES в другое значение для подпроцесса ничего не делает.
Хуже того, для инициализации достаточно вызова torch.cuda.device_count()
CUDA, поэтому мы не можем даже запросить количество графических процессоров из PyTorch. Решением является либо жесткое его кодирование, передача в качестве параметра, либо запрос PyTorch API в отдельном процессе. Моя реализация для последнего:
import sys
def get_available_gpus_without_triggering_pytorch_cuda_initialization(envvars):
import subprocess
out = subprocess.run([sys.executable, '-m', 'utils.get_available_gpus'], capture_output=True, env=envvars)
text_output = out.stdout.decode()
from utils.utils import log
log.debug('Queried available GPUs: %s', text_output)
return text_output
def main():
import torch
device_count = torch.cuda.device_count()
available_gpus = ','.join(str(g) for g in range(device_count))
print(available_gpus)
return 0
if __name__ == '__main__':
sys.exit(main())
По сути, эта функция вызывает свой собственный скрипт как отдельный python процесс и читает стандартный вывод.
Я не буду отмечать этот ответ как принятый, потому что я бы хотел бы узнать правильное решение, если оно существует.