"일꾼이 일을 잘하려면 먼저 도구를 갈고 닦아야 한다." - 공자, 『논어』.
첫 장 > 프로그램 작성 > 실시간 애플리케이션을 위한 Supersonic GPU MelSpectrogram

실시간 애플리케이션을 위한 Supersonic GPU MelSpectrogram

2024-11-08에 게시됨
검색:744

Supersonic GPU MelSpectrogram for your real-time applications

Simli에서는 지연 시간을 가장 중요하게 생각합니다. 결국 우리가 추구하는 것은 저지연 비디오입니다. 반면에 오디오 머신러닝에서 가장 많이 사용되는 알고리즘 중 일부는 구현 속도가 매우 느립니다. 분명히 말하면 이러한 구현은 일반적으로 모델 자체를 생성하거나 일괄 추론에 적합합니다. 그러나 Simli에서는 몇 밀리초가 끊김이 심한 영상인지 부드러운 영상인지의 차이를 의미할 수 있습니다.
운이 좋게도 (그리고 독자 여러분을 대신해) 이 가이드에는 수학에 대한 많은 지식이 필요하지 않습니다. 훨씬 더 똑똑한 사람들은 이미 정답을 얻는 방법을 알아냈으며 우리는 단지 계산을 더 효율적으로 만들고 있을 뿐입니다. MelSpectrogram이 무엇인지 이해하기 위해 더 많은 정보가 필요하다면 이 기사를 읽어보세요. 스펙트로그램을 계산하는 방법은 여러 가지가 있으며 응용 프로그램에 따라 크게 달라집니다. 그래서 작성자의 편의를 위해 내부 모델을 실행하는 데 필요한 멜에 중점을 두고 있습니다.

일반적인 솔루션: Librosa

당신은 Librosa를 사용하는 저장소를 만난 후 여기에 왔을 가능성이 높습니다. 솔직히 말해서 꽤 편리한 라이브러리입니다. 수많은 유틸리티, 디스크의 오디오를 읽는 쉬운 방법, 오디오 리샘플링, 채널 다운믹싱 등과 같이 일반적으로 필요한 많은 기능에 대한 빠른 액세스가 있습니다. 우리의 경우에는 멜스펙트로그램 계산이라는 특정 기능에 관심이 있습니다. librosa에서는 멜스펙트로그램을 얻는 것이 간단합니다.

import librosa

# load in any audio to test
sampleAudio, sr = librosa.load("sample.mp3", sr=None) # sr=None means the original sampling rate
spectrogram = librosa.feature.melspectrogram(
    y=sampleAudio,
    sr=sr,
    n_fft=int(0.05 * sr),  # 50ms
    hop_length=int(0.0125 * sr),  # 12.5ms
    win_length=int(0.05 * sr),
)

간단하며 GCP g2 VM에서는 평균 약 2ms가 걸립니다. 음, 두 가지 주요 문제가 있습니다:

  1. 일반적으로 DL 모델로 작업할 때는 GPU에서 모델을 실행해야 합니다. 이는 체인의 일부가 CPU에서 실행된 다음 결과를 다시 GPU에 복사한다는 의미입니다. 일괄 추론의 경우 GPU/전송에 들어갈 수 있는 만큼의 데이터를 수집해야 하기 때문에 이는 대부분 괜찮습니다. 하지만 우리의 경우 대기 시간과 처리 시간을 줄이기 위해 한 번에 한 프레임씩 작업하는 경우가 많습니다.
  2. 총 시간 예산은 대략 프레임당 33ms입니다. 여기에는 API 서버에서 ML 추론 서버로의 전송 지연 시간, CPU에서 GPU로의 복사, 전처리, 멜스펙트로그램을 포함한 모델에 대한 후처리가 포함됩니다. 이렇게 빠듯한 예산으로 작업할 때는 1000분의 1초가 중요합니다. 이 2밀리초는 실제로 Simli의 실시간 렌더링 비디오 스트림을 작동하는 데 기여했습니다(각각 1~2밀리초에 해당하는 많은 최적화였습니다).

온라인에서 솔루션 찾기

다른 사람들이 어떻게 했는지 살펴보는 동안(다행히 이것은 우리에게만 있는 문제는 아닙니다) 멜스펙트로그램의 작동 방식을 설명하고 어떤 이유로 1ms(50 % 개선). 좋은 시작이지만 여전히 첫 번째 문제가 있습니다. 모든 것이 GPU에 있는 것은 아닙니다. 우리는 PyTorch를 사용하고 있으며 최대 속도 향상을 위해 mode=reduce-overhead를 사용하여 torch.compile에 의존해 왔습니다. 그러나 이와 같은 데이터 전송은 PyTorch 컴파일러가 기능을 최적화할 수 없기 때문에 성능을 저하시킬 수 있습니다. 해결책은 약간 지루하지만 상대적으로 쉽습니다. 토치로 다시 작성하세요. PyTorch 팀은 많은 구문과 기능이 가능한 한 NumPy에 가깝도록 만들었습니다(이틀 동안 헤매었지만 다른 블로그에 대한 이야기인 경우를 제외하고는 일반적으로 잘 문서화되어 있는 일부 극단적인 경우 포함). .

PyTorch 재작성

Pytorch의 모든 것을 성공적으로 다시 작성하려면 몇 가지 단계를 수행해야 합니다. 멜스펙트로그램은 세 단계로 나눌 수 있습니다:

  • 단시간 푸리에 변환 계산
  • 멜 스케일 주파수 뱅크 생성
  • 스펙트로그램을 생성합니다.

좋은 소식과 나쁜 소식이 있습니다. 좋은 소식은 필요한 모든 기능을 pytorch나 torchaudio에서 쉽게 사용할 수 있다는 것입니다. 나쁜 소식은 기본 동작이 librosa와 많이 다르기 때문에 올바르게 설정하려면 많은 구성과 시행착오가 필요하다는 것입니다. 나는 그런 일을 겪었고 내 최악의 적에게 그런 일이 일어나기를 바랄 수도 없기 때문에 정보를 공유하고 있습니다. 우리가 이해해야 할 한 가지는 이 코드가 나중에 사용하기 위해 일부 결과를 캐싱하는 데 크게 의존한다는 것입니다. 이는 모든 정적 배열을 미리 생성하는 초기화 기능에서 수행됩니다(예를 들어 멜 주파수 뱅크는 샘플링 속도와 필요한 멜 수에 따라 다릅니다). PyTorch를 사용하여 최적화된 melspectrogram 기능 버전은 다음과 같습니다.

import torch

if torch.cuda.is_available
    @torch.compile(mode="reduce-overhead")
else:
    @torch.compile
def melspecrogram_torch(wav:torch.Tensor,sample_rate:int, hann_window: torch.Tensor, mel_basis: torch.Tensor):
    stftWav = torch.stft(
            wav,
            n_fft=int(sample_rate*0.05),
            win_length=int(sample_rate*0.05),
            hop_length=int(sample_rate*0.0125),
            window=hann_window,
            pad_mode="constant",
            return_complex=True,
        ).abs()
    stftWav = stftWav.squeeze()
    mel_stftWav = torch.mm(mel_basis, stftWav)
    return mel_stftWav

device = "cuda" if torch.cuda.is_available() else "cpu"

melspectrogram_torch(
    sampleAudio,
    sr,
    torch.hann_window(int(sample_rate*0.05), device=device, dtype=torch.float32),
    torchaudio.functional.melscale_fbanks(
        sample_rate=sr,
        n_freqs=(int(sample_rate*0.05) // 2   1),
        norm="slaney", # this is the normalization algorithm used by librosa
        # this is an example that's related to our own pipeline, check what you need for yours
        n_mels=80,
        f_min=55,
        f_max=7600,
    )
    .T.to(device)
)

초기 컴파일 실행 후 Nvidia L4 GPU(hann_window 및 melscale_fbanks 캐싱 사용)를 사용하여 이 함수가 350마이크로초가 걸리는 것으로 측정했습니다. 조정된 통화는 다음과 같습니다:

hann=torch.hann_window(int(sample_rate*0.05), device=device, dtype=torch.float32),
melscale=torchaudio.functional.melscale_fbanks(
        sample_rate=sr,
        n_freqs=(int(sample_rate*0.05) // 2   1),
        norm="slaney", # this is the normalization algorithm used by librosa
        # this is an example that's related to our own pipeline, check what you need for yours
        n_mels=80,
        f_min=55,
        f_max=7600,
    )
    .T.to(device)
melspectrogram_torch(
    sampleAudio,
    sr,
    hann,
    melscale,
)

이 내용은 사전 학습된 모델 배포를 최적화하고 전처리 및 후처리 단계를 최적화하는 방법에 대한 일련의 기사 중 하나입니다. https://www.simli.com/demo를 확인하여 배포된 모델과 우리가 제공하는 가장 낮은 대기 시간 아바타를 확인할 수 있습니다

릴리스 선언문 이 기사는 https://dev.to/simli_ai/supersonic-gpu-melspectrogram-for-your-real-time-applications-gg1?1에서 복제됩니다. 침해 내용이 있는 경우, [email protected]으로 연락하여 삭제하시기 바랍니다. 그것
최신 튜토리얼 더>

부인 성명: 제공된 모든 리소스는 부분적으로 인터넷에서 가져온 것입니다. 귀하의 저작권이나 기타 권리 및 이익이 침해된 경우 자세한 이유를 설명하고 저작권 또는 권리 및 이익에 대한 증거를 제공한 후 이메일([email protected])로 보내주십시오. 최대한 빨리 처리해 드리겠습니다.

Copyright© 2022 湘ICP备2022001581号-3