「労働者が自分の仕事をうまくやりたいなら、まず自分の道具を研ぎ澄まさなければなりません。」 - 孔子、「論語。陸霊公」
表紙 > プログラミング > リアルタイム アプリケーション向けの Supersonic GPU MelSpectrogram

リアルタイム アプリケーション向けの Supersonic GPU MelSpectrogram

2024 年 11 月 8 日に公開
ブラウズ:592

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 では平均で約 2 ミリ秒かかります。そうですね、主な問題が 2 つあります:

  1. 通常、DL モデルを使用する場合は、モデルを GPU で実行する必要があります。これは、チェーンの一部が CPU 上で実行され、結果を GPU にコピーして戻すことを意味します。バッチ推論の場合、GPU/転送に収まる限り多くのデータを収集する必要があるため、これはほとんど問題ありません。ただし、私たちの場合、待機時間と処理時間を短縮するために、一度に 1 つのフレームを処理することがよくあります。
  2. 合計の時間予算はおよそ 33 ミリ秒/フレームです。これには、API サーバーから ML 推論サーバーへの転送レイテンシ、CPU から GPU へのコピー、メルスペクトログラムを含むモデルの前処理、後処理が含まれます。予算が限られている場合は、1 ミリ秒も重要になります。この 2 ミリ秒は、実際に Simli のライブ レンダリング ビデオ ストリームの動作に貢献しました (まあ、それぞれ 1 ~ 2 ミリ秒に相当する多くの最適化でした)。

オンラインで解決策を探す

他の人がどのようにそれを実行したかを見ようとしていたときに (幸いなことに、これは私たちに特有の問題ではありません)、メルスペクトログラムがどのように機能するかを説明し、何らかの理由でわずか 1 ミリ秒 (50 ミリ秒) しかかからなかったリファレンス実装を提供するこの記事を見つけました。 % 改善)。これは良いスタートですが、最初の問題がまだ残っています。すべてが GPU 上にあるわけではありません。私たちは PyTorch を使用しており、最大速度の向上のために、mode=reduce-overhead を指定した torch.compile に依存しています。ただし、このようなデータ転送は、PyTorch コンパイラーが関数を最適化できないため、パフォーマンスが低下する可能性があります。解決策は少し面倒ですが、比較的簡単です。torch で書き直します。 PyTorch チームは、多くの構文と機能が可能な限り NumPy に近づくようにしました (いくつかのエッジ ケースは、通常は十分に文書化されていますが、私が数日費やしたケースは別ですが、これは別のブログでの話です) .

PyTorch の書き換え

Pytorch ですべてを正常に書き直すには、いくつかの手順を実行する必要があります。メルスペクトログラムは 3 つのステップに分割できます:

  • コンピューティング短時間フーリエ変換
  • メルスケール周波数バンクの生成
  • スペクトログラムを生成しています。

良いニュースと悪いニュースがあります。良いニュースは、必要な機能がすべて pytorch または torchaudio ですぐに利用できることです。悪いニュースは、デフォルトの動作が librosa とは大きく異なるため、正しく動作させるには多くの設定と試行錯誤が必要になることです。私はそれを経験しており、最悪の敵に地獄を望むことさえできないので、情報を共有しています。理解する必要があることの 1 つは、このコードは後で使用するために結果の一部をキャッシュすることに大きく依存しているということです。これは、すべての静的配列を事前生成する初期化関数で行われます (たとえば、メル周波数バンクはサンプリング レートと必要なメルの数に依存します)。これは、PyTorch
を使用したメルスペクトログラム関数の最適化バージョンです。

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