Maison >développement back-end >Tutoriel Python >Notes sur la conférence 1 en mode GPU

Notes sur la conférence 1 en mode GPU

DDD
DDDoriginal
2024-11-17 19:21:021036parcourir

Notes on GPU-Mode lecture 1

Profileur

Les performances informatiques sont une question de compromis en matière de temps et de mémoire. Étant donné que les appareils de calcul sont beaucoup plus chers, la plupart du temps, le temps est la priorité à prendre en compte.

Pourquoi utiliser un profileur ?

  1. CUDA est asynchrone et ne peut donc pas utiliser le module de temps Python
  2. Les profileurs sont bien plus puissants

Outils

Il existe trois profileurs :

  • profileur autograd : numérique
  • Profileur Pytorch : visuel
  • NVIDIA Nsight Calcul

Le profileur Autograd utilise torch.cuda.Event() pour mesurer les performances.

Le profileur PyTorch utilise la méthode profile() du gestionnaire de contexte Profiler torch.profiler pour analyser les performances.
Vous pouvez exporter le résultat sous forme de fichier .json et le télécharger sur chrome://tracing/ pour le visualiser.

Démo

Le cours fournit un programme simple pour montrer comment utiliser le profileur autograd pour analyser les performances de trois façons d'effectuer des opérations carrées :

  • par torch.square()
  • par **opérateur
  • par *opérateur
def time_pytorch_function(func, input):
    # CUDA IS ASYNC so can't use python time module
    start = torch.cuda.Event(enable_timing=True)
    end = torch.cuda.Event(enable_timing=True)

    # Warmup
    for _ in range(5):
        func(input)

    start.record()
    func(input)
    end.record()
    torch.cuda.synchronize()
    return start.elapsed_time(end)

time_pytorch_function(torch.square, b)
time_pytorch_function(square_2, b)
time_pytorch_function(square_3, b)

Le résultat ci-dessous est réalisé sur le GPU NVIDIA T4.

Profiling torch.square:
Self CPU time total: 10.577ms
Self CUDA time total: 3.266ms

Profiling a * a:
Self CPU time total: 5.417ms
Self CUDA time total: 3.276ms

Profiling a ** 2:
Self CPU time total: 6.183ms
Self CUDA time total: 3.274ms

Il s'avère :

  • Le fonctionnement de CUDA est plus rapide que celui du CPU.
  • L'opérateur * effectue une opération aten::multiply plutôt qu'une opération aten::pow, et la première est plus rapide. C'est probablement parce que ce multiplie est plus utilisé que pow et que de nombreux développeurs passent du temps à l'optimiser.
  • La différence de performances sur CUDA est minime. torch.square est l'opération la plus lente compte tenu du temps CPU
  • aten::square est un appel à aten::pow
  • Les trois méthodes ont lancé un noyau cuda appelé native::vectorized_elementwise_kernel<4, à...

Intégration des noyaux CUDA dans PyTorch

Il existe plusieurs façons de procéder :

  • utilisez load_inline depuis torch.utils.cpp_extendsion
  • utilisez Numba qui est un compilateur qui compile une fonction Python décorée dans le code machine qui s'exécute à la fois sur CPU et GPU
  • utiliser Triton

Nous pouvons utiliser load_inline depuis torch.utils.cpp_extendsion pour charger le noyau CUDA en tant qu'extension PyTorch par load_inline(name, cpp_sources, cuda_sources, function, with_cuda, build_directory).

from torch.utils.cpp_extension import load_inline

square_matrix_extension = load_inline(
    name='square_matrix_extension',
    cpp_sources=cpp_source,
    cuda_sources=cuda_source,
    functions=['square_matrix'],
    with_cuda=True,
    extra_cuda_cflags=["-O2"],
    build_directory='./load_inline_cuda',
    # extra_cuda_cflags=['--expt-relaxed-constexpr']
)

a = torch.tensor([[1., 2., 3.], [4., 5., 6.]], device='cuda')
print(square_matrix_extension.square_matrix(a))

Pratique

Utiliser le profileur Autograd en fonctionnement moyen

Lorsque vous utilisez le profileur Autograd, n'oubliez pas :

  1. Réchauffez le GPU avant l'enregistrement afin que le GPU entre dans un état stable
  2. Faites la moyenne de plusieurs exécutions pour des résultats plus fiables
def time_pytorch_function(func, input):
    # CUDA IS ASYNC so can't use python time module
    start = torch.cuda.Event(enable_timing=True)
    end = torch.cuda.Event(enable_timing=True)

    # Warmup
    for _ in range(5):
        func(input)

    start.record()
    func(input)
    end.record()
    torch.cuda.synchronize()
    return start.elapsed_time(end)

time_pytorch_function(torch.square, b)
time_pytorch_function(square_2, b)
time_pytorch_function(square_3, b)

Utiliser le profileur Pytorch en fonctionnement moyen

Profiling torch.square:
Self CPU time total: 10.577ms
Self CUDA time total: 3.266ms

Profiling a * a:
Self CPU time total: 5.417ms
Self CUDA time total: 3.276ms

Profiling a ** 2:
Self CPU time total: 6.183ms
Self CUDA time total: 3.274ms

Implémentation du code triton pour torch.mean()

from torch.utils.cpp_extension import load_inline

square_matrix_extension = load_inline(
    name='square_matrix_extension',
    cpp_sources=cpp_source,
    cuda_sources=cuda_source,
    functions=['square_matrix'],
    with_cuda=True,
    extra_cuda_cflags=["-O2"],
    build_directory='./load_inline_cuda',
    # extra_cuda_cflags=['--expt-relaxed-constexpr']
)

a = torch.tensor([[1., 2., 3.], [4., 5., 6.]], device='cuda')
print(square_matrix_extension.square_matrix(a))

Référence

  • Conférences en mode GPU - Github
  • Événement - Pytorch
  • Profileur PyTorch
  • NVIDIA Nsight Calcul
  • torch.utils.cpp_extension.load_inline
  • Triton

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn