Heim  >  Artikel  >  Backend-Entwicklung  >  Hinweise zur GPU-Mode-Vorlesung 1

Hinweise zur GPU-Mode-Vorlesung 1

DDD
DDDOriginal
2024-11-17 19:21:02965Durchsuche

Notes on GPU-Mode lecture 1

Profiler

Bei der Computerleistung geht es um Zeit- und Speicherkompromisse. Da Rechengeräte viel teurer sind, steht in den meisten Fällen die Zeit im Vordergrund.

Warum einen Profiler verwenden?

  1. CUDA ist asynchron und kann daher das Python-Zeitmodul nicht verwenden
  2. Profiler sind viel leistungsfähiger

Werkzeuge

Es gibt drei Profiler:

  • Autograd-Profiler: numerisch
  • Pytorch-Profiler: visuell
  • NVIDIA Nsight Compute

Der Autograd-Profiler verwendet Torch.cuda.Event(), um die Leistung zu messen.

Der PyTorch-Profiler nutzt die Methode „profile()“ des Profiler-Kontextmanagers „torch.profiler“, um die Leistung zu analysieren.
Sie können das Ergebnis als .json-Datei exportieren und zur Visualisierung auf chrome://tracing/ hochladen.

Demo

Der Kurs stellt ein einfaches Programm bereit, das zeigt, wie man mit dem Autograd-Profiler die Leistung von drei Möglichkeiten zur Durchführung von Quadratoperationen analysiert:

  • von Torch.square()
  • vom **-Operator
  • vom *-Operator
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)

Das folgende Ergebnis wurde auf der NVIDIA T4-GPU erstellt.

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

Es stellt sich heraus:

  • Der CUDA-Betrieb ist schneller als die CPU.
  • Der *-Operator führt eine aten::multiply-Operation anstelle einer aten::pow-Operation aus, und erstere ist schneller. Das liegt wahrscheinlich daran, dass Multiply mehr als Pow verwendet wird und viele Entwickler Zeit damit verbringen, es zu optimieren.
  • Der Leistungsunterschied bei CUDA ist minimal. Torch.square ist angesichts der CPU-Zeit der langsamste Vorgang
  • aten::square ist ein Aufruf an aten::pow
  • Alle drei Methoden starteten einen Cuda-Kernel namens native::vectorized_elementwise_kernel<4, um...

Integration von CUDA-Kerneln in PyTorch

Es gibt mehrere Möglichkeiten, dies zu tun:

  • Verwenden Sie Load_inline aus Torch.utils.cpp_extendsion
  • Verwenden Sie Numba, einen Compiler, der eine dekorierte Python-Funktion in den Maschinencode kompiliert, der sowohl auf der CPU als auch auf der GPU läuft
  • Triton verwenden

Wir können Load_inline von Torch.utils.cpp_extendsion verwenden, um den CUDA-Kernel als PyTorch-Erweiterung durch Load_inline(Name, CPP_Sources, Cuda_Sources, Funktionen, With_Cuda, Build_Directory) zu laden.

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))

Praktisch

Verwenden Sie den Autograd-Profiler für den mittleren Betrieb

Beachten Sie bei der Verwendung des Autograd-Profilers Folgendes:

  1. Wärmen Sie die GPU vor der Aufnahme auf, damit die GPU in einen stabilen Zustand übergeht
  2. Durchschnitt mehrerer Durchläufe für zuverlässigere Ergebnisse
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)

Verwenden Sie den Pytorch-Profiler für den mittleren Betrieb

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

Triton-Code für Torch.mean() implementieren

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))

Referenz

  • GPU-Modus-Vorlesungen – Github
  • Ereignis – Pytorch
  • PyTorch Profiler
  • NVIDIA Nsight Compute
  • torch.utils.cpp_extension.load_inline
  • Triton

Das obige ist der detaillierte Inhalt vonHinweise zur GPU-Mode-Vorlesung 1. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn