Whisper batch generation is not faster than loops
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 4.7k
- Forks
- 536
- Avg merge
- 12h 12m
- Merged PRs (30d)
- 4
Description
In CTranslate2 Whisper model, batch generate is not faster than looping one by one. I tried the same thing on Translator model and it shows batching is far superior (a lot faster). I used Whisper small converted to int8 using ct2 tool. Also, GPU memory is higher when batching so I thought CTranslate2 is doing "proper" batching (and not a looping wrapper). Here is my simple Whisper code.
import time
import numpy as np
from ctranslate2 import StorageView
from ctranslate2.models import Whisper
from transformers import WhisperProcessor
def make_prompts(tokenizer, n: int) -> list[list[int]]:
prompt = tokenizer.convert_tokens_to_ids(
[
"<|startoftranscript|>",
"<|en|>",
"<|transcribe|>",
]
)
return [prompt] * n
def loop(
whisper: Whisper,
features: list[StorageView],
prompts: list[list[int]],
):
for feat, prompt in zip(features, prompts):
_ = whisper.generate(
feat,
[prompt],
return_scores=True,
return_no_speech_prob=True,
)
def batch(
whisper: Whisper,
features: StorageView,
prompts: list[list[int]],
):
_ = whisper.generate(
features,
prompts,
return_scores=True,
return_no_speech_prob=True,
)
def main():
N_SAMPLES = 8
N_SEC = 5
SR = 16000
# load model and processor
whisper = Whisper("models/whisper-small", device="cuda")
processor = WhisperProcessor.from_pretrained("openai/whisper-small")
tokenizer = processor.tokenizer
# generate required data
chunks = np.random.random((N_SAMPLES, N_SEC * SR)).astype(np.float32)
inputs = processor(chunks, return_tensors="np", sampling_rate=SR)
mels = inputs["input_features"]
features_loop = [StorageView.from_array(m[None, :]) for m in mels]
features_batch = StorageView.from_array(mels)
prompts = make_prompts(tokenizer, N_SAMPLES)
# warm up
print("warming up... ", end="", flush=True)
for _ in range(7):
loop(whisper, features_loop, prompts)
batch(whisper, features_batch, prompts)
print("done")
N = 20
print(f"benchmarking each method for {N} iterations")
# loop time
t0 = time.perf_counter()
for _ in range(N):
loop(whisper, features_loop, prompts)
elapsed = time.perf_counter() - t0
print(f"loop time: {elapsed:0.3f} secs")
# batch time
t0 = time.perf_counter()
for _ in range(N):
batch(whisper, features_batch, prompts)
elapsed = time.perf_counter() - t0
print(f"batch time: {elapsed:0.3f} secs")
main()
When I ran the code on colab (T4 GPU), it outputs:
benchmarking each method for 20 iterations
loop time: 25.311 secs
batch time: 30.086 secs
Is there anything I could do to increase the speed of Whisper batch generation?
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Run the supplied Python benchmark on the CTranslate2 Whisper entry point, comparing Whisper.generate with batched and one-at-a-time StorageView inputs. Trace the batching path and measure whether the change improves batch generation against the reported loop baseline on equivalent inputs.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp, numpy, python
- Domain
- machine-learning, performance
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100