Increasing throughput with batches and quantization

#11
by miguelcarv - opened

I have been trying to increase throughput of CogVLM by using batches like other issue here advised and with a A100 I've been able to use a batch size of 16 and output on average 3.5 seconds per image. This still needs to be faster for my use case so I tried other methods and the only one that seemed faster to get to work is to load the model in 4 or 8 bit and increase the batch size, but I can't seem to get the inputs data types correct.I get the following message:

UserWarning: Input type into Linear4bit is torch.float16, but bnb_4bit_compute_type=torch.float32 (default). This will lead to slow inference or training speed.
  warnings.warn(f'Input type into Linear4bit is torch.float16, but bnb_4bit_compute_type=torch.float32 (default). This will lead to slow inference or training speed.')

Any other common datatype raises an error... Here's the code:

import torch
import requests
from PIL import Image
from transformers import AutoModelForCausalLM, LlamaTokenizer
import time
import os

tokenizer = LlamaTokenizer.from_pretrained('lmsys/vicuna-7b-v1.5')

model = AutoModelForCausalLM.from_pretrained(
    'THUDM/cogvlm-chat-hf',
    low_cpu_mem_usage=True,
    trust_remote_code=True,
    load_in_4bit=True
).eval()

images = os.listdir("/tmp/textcaps/train_images/")

input_list = [model.build_conversation_input_ids(
    tokenizer,
    images=[Image.open("/tmp/textcaps/train_images/"+i).convert('RGB'),],
    query='Describe this image in detail',  # Q1
    history=[], 
    )
    for i in images[:16]]

def recur_move_to(item, tgt, criterion_func):
    if criterion_func(item):
        device_copy = item.to(tgt)
        return device_copy
    elif isinstance(item, list):
        return [recur_move_to(v, tgt, criterion_func) for v in item]
    elif isinstance(item, tuple):
        return tuple([recur_move_to(v, tgt, criterion_func) for v in item])
    elif isinstance(item, dict):
        return {k: recur_move_to(v, tgt, criterion_func) for k, v in item.items()}
    else:
        return item

def collate_fn(features, tokenizer) -> dict:
    images = [feature.pop('images') for feature in features]
    tokenizer.padding_side = 'left'
    padded_features = tokenizer.pad(features)
    inputs = {**padded_features, 'images': images}
    return inputs

input_batch = collate_fn(input_list, tokenizer)
input_batch = recur_move_to(input_batch, 'cuda', lambda x: isinstance(x, torch.Tensor))
input_batch = recur_move_to(input_batch, torch.float16, lambda x: isinstance(x, torch.Tensor) and torch.is_floating_point(x))

gen_kwargs = {"max_length": 2048, "do_sample": False}

t1 = time.time()
with torch.no_grad():
    outputs = model.generate(**input_batch, **gen_kwargs)
    outputs = outputs[:, input_batch['input_ids'].shape[1]:]
    print(tokenizer.batch_decode(outputs))

print(time.time() - t1)

If there are any other suggestions for increasing throughput I am also more than willing to accept. I have a node of 4 A100's and 6 GPUs with 50Gb of memory each.

for the issue mentioned, just use the BitsAndBytesConfig to set the compute type


from transformers import AutoModelForCausalLM, LlamaTokenizer, BitsAndBytesConfig

bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_use_double_quant=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.bfloat16
)

max_memory_mapping = {0: "23GB", 1: "23GB"}

model = AutoModelForCausalLM.from_pretrained(
    'THUDM/cogvlm-chat-hf',
    low_cpu_mem_usage=True,
    trust_remote_code=True,
    quantization_config=bnb_config,
    max_memory=max_memory_mapping
).eval()

using 4bit quantisation with batch size 16 processing, on an L4 was able to achieve inference time of 4 sec/image. compared to 15s per image without quantisation and batch

I attempted to quantize CogVLM using AutoGPTQ. Quantization was successful, but inference failed.

chenkq pinned discussion

@neil651 I'm following your BitsAndBytes quantization strategy. It loads fine onto the GPU, but when trying inference I get datatype errors for input vs inference.

  File "/home/user/mambaforge/envs/tensorml/lib/python3.11/site-packages/torch/nn/modules/conv.py", line 456, in _conv_forward
    return F.conv2d(input, weight, bias, self.stride,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
RuntimeError: Input type (c10::BFloat16) and bias type (c10::Half) should be the same

Can you post a whole example of your bitsandbytes 4bit quant with inference?

Knowledge Engineering Group (KEG) & Data Mining at Tsinghua University org

@z3ugma change the bnb_4bit_compute_dtype=torch.bfloat16 to bnb_4bit_compute_dtype=torch.float16 may help

Knowledge Engineering Group (KEG) & Data Mining at Tsinghua University org

Just change your image type from bf16 to fp16 is ok.

'images': [[inputs['images'][0].to('cuda').to(torch.float16)]],

@qingsonglv that was the solution to making 4-bit quantized work. With that in place, the model takes up only 12GiB on a 16GB CUDA Nvidia GPU

Sign up or log in to comment