Sémantique HIP (ROCm)
ROCm est la plateforme logicielle open source d'AMD pour le calcul haute performance accéléré par GPU et l'apprentissage automatique. HIP est le dialecte C++ de ROCm, conçu pour faciliter la conversion des applications CUDA en code C++ portable. HIP est utilisé pour la conversion d'applications CUDA existantes, comme PyTorch, en C++ portable, et pour les nouveaux projets nécessitant une portabilité entre AMD et NVIDIA.
Interfaces HIP : réutilisation des interfaces CUDA
PyTorch pour HIP réutilise intentionnellement les interfaces torch.cuda existantes. Cela accélère le portage du code et des modèles PyTorch existants, car très peu de modifications sont nécessaires, voire aucune.
L'exemple de la sémantique CUDA fonctionnera exactement de la même manière pour HIP :
- cuda = torch.device('cuda') # Dispositif HIP par défaut
- cuda0 = torch.device('cuda:0') # « rocm » ou « hip » ne sont pas valides, utilisez « cuda »
- cuda2 = torch.device('cuda:2') # GPU 2 (ceux-ci sont indexés 0)
-
- x = torch.tensor([1., 2.], device=cuda0)
- # x.device est un périphérique (type='cuda', index=0)
- y = torch.tensor([1., 2.]).cuda()
- # y.device est un périphérique (type='cuda', index=0)
-
- with torch.cuda.device(1):
- # alloue un tenseur sur le GPU 1
- a = torch.tensor([1., 2.], device=cuda)
-
- # transfère un tenseur du CPU au GPU 1
- b = torch.tensor([1., 2.]).cuda()
- # a.device and b.device are device(type='cuda', index=1)
-
- # Vous pouvez également utiliser « Tensor.to » pour transférer un tenseur :
- b2 = torch.tensor([1., 2.]).to(device=cuda)
- # b.device et b2.device sont des périphériques (type='cuda', index=1)
-
- c = a + b
- # c.device est un périphérique (type='cuda', index=1)
-
- z = x + y
- # z.device est un périphérique (type='cuda', index=0)
-
- # même dans un contexte, vous pouvez spécifier le périphérique (ou donner un index GPU à l'appel .cuda)
- d = torch.randn(2, device=cuda2)
- e = torch.randn(2).to(cuda2)
- f = torch.randn(2).cuda(cuda2)
- # d.device, e.device et f.device sont tous des périphériques (type='cuda', index=2)
Vérification de la compatibilité HIP
Que vous utilisiez PyTorch pour CUDA ou HIP, l'appel à is_available() aura le même résultat. Si vous utilisez une version de PyTorch compatible GPU, elle renverra True. Pour vérifier la version de PyTorch que vous utilisez, consultez l'exemple ci-dessous :
- if torch.cuda.is_available() and torch.version.hip:
- # faire quelque chose de spécifique pour HIP
- elif torch.cuda.is_available() and torch.version.cuda:
- # faire quelque chose de spécifique pour CUDA
TensorFloat-32 (TF32) sur ROCm
TF32 n'est pas pris en charge sur ROCm.
Gestion de la mémoire
PyTorch utilise un allocateur de mémoire cache pour accélérer les allocations de mémoire. Cela permet une désallocation rapide de la mémoire sans synchronisation des périphériques. Cependant, la mémoire inutilisée gérée par l'allocateur sera toujours affichée comme utilisée dans rocm-smi. Vous pouvez utiliser memory_allocated() et max_memory_allocated() pour surveiller la mémoire occupée par les tenseurs, et memory_reserved() et max_memory_reserved() pour surveiller la quantité totale de mémoire gérée par l'allocateur de mise en cache. L'appel à empty_cache() libère toute la mémoire cache inutilisée de PyTorch afin qu'elle puisse être utilisée par d'autres applications GPU. Cependant, la mémoire GPU occupée par les tenseurs ne sera pas libérée, ce qui ne permettra pas d'augmenter la quantité de mémoire GPU disponible pour PyTorch.
Pour les utilisateurs plus expérimentés, nous proposons une analyse comparative plus complète de la mémoire via memory_stats(). Nous offrons également la possibilité de capturer un instantané complet de l'état de l'allocateur de mémoire via memory_snapshot(), ce qui peut vous aider à comprendre les schémas d'allocation sous-jacents produits par votre code.
Pour déboguer les erreurs de mémoire, définissez PYTORCH_NO_HIP_MEMORY_CACHING=1 dans votre environnement pour désactiver la mise en cache. PYTORCH_NO_CUDA_MEMORY_CACHING=1 est également accepté pour faciliter le portage.
Espaces de travail hipBLAS
Pour chaque combinaison de descripteur hipBLAS et de flux HIP, un espace de travail hipBLAS est alloué si cette combinaison exécute un noyau hipBLAS nécessitant un espace de travail. Afin d'éviter des allocations répétées, ces espaces de travail ne sont pas désalloués, sauf si torch._C._cuda_clearCublasWorkspaces() est appelé ; il s'agit de la même fonction pour CUDA et HIP. La taille de l'espace de travail par allocation peut être spécifiée via la variable d'environnement HIPBLAS_WORKSPACE_CONFIG au format : [SIZE]: [COUNT]. Par exemple, la variable d'environnement HIPBLAS_WORKSPACE_CONFIG=:4096:2:16:8 spécifie une taille totale de 2 * 4096 + 8 * 16 Kio, soit 8 Mio. La taille par défaut de l'espace de travail est de 32 Mio ; pour MI300 et les versions ultérieures, la taille par défaut est de 128 Mio. Pour forcer hipBLAS à éviter d'utiliser les espaces de travail, définissez HIPBLAS_WORKSPACE_CONFIG=:0:0. Pour plus de commodité, CUBLAS_WORKSPACE_CONFIG est également accepté.
Cache des plans hipFFT/rocFFT
La définition de la taille du cache pour les plans hipFFT/rocFFT n'est pas prise en charge.
Backends torch.distributed
Actuellement, seuls les backends «nccl» et «gloo» pour torch.distributed sont pris en charge sur ROCm.
Cartographie de l'API CUDA vers API HIP en C++
Veuillez consulter : https://rocmdocs.amd.com/en/latest/Programming_Guides/HIP_API_Guide.html
Remarque : La macro CUDA_VERSION et les API cudaRuntimeGetVersion et cudaDriverGetVersion ne correspondent pas sémantiquement aux mêmes valeurs que la macro HIP_VERSION et les API hipRuntimeGetVersion et hipDriverGetVersion. Veuillez ne pas les utiliser de manière interchangeable lors des vérifications de version.
Par exemple, au lieu d'utiliser :
- #if defined(CUDA_VERSION) && CUDA_VERSION >= 11000
pour exclure implicitement ROCm/HIP, utilisez ce qui suit pour ne pas emprunter le chemin du code pour ROCm/HIP :
- #if defined(CUDA_VERSION) && CUDA_VERSION >= 11000 && !defined(USE_ROCM)
Alternativement, si vous souhaitez emprunter le chemin du code pour ROCm/HIP :
- #if (defined(CUDA_VERSION) && CUDA_VERSION >= 11000) || defined(USE_ROCM)
Ou si vous souhaitez suivre le chemin du code pour ROCm/HIP uniquement pour des versions HIP spécifiques :
- #if (defined(CUDA_VERSION) && CUDA_VERSION >= 11000) || (defined(USE_ROCM) && ROCM_VERSION >= 40300)
Consultez la documentation sur la sémantique CUDA
Pour toute section non répertoriée ici, veuillez consulter la documentation sur la sémantique CUDA : Sémantique CUDA.
Activation des assertions du noyau
Les assertions du noyau sont prises en charge sur ROCm, mais elles sont désactivées en raison d'une baisse de performances. Elles peuvent être activées en recompilant PyTorch depuis les sources.
Veuillez ajouter la ligne ci-dessous comme argument aux paramètres de la commande cmake :
| -DROCM_FORCE_ENABLE_GPU_ASSERTS:BOOL=ON |