quantization2 / llm-awq /tinychat /modules /fused_siglipdecoder.py
chen459664's picture
Add files using upload-large-folder tool
11690a5 verified
Raw
History Blame Contribute Delete
9.91 kB
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
from awq.quantize import W8A8OF16LinearDynamicInputScale
from llava.model.multimodal_encoder.siglip.modeling_siglip import (
SiglipMLP,
SiglipEncoder,
SiglipAttention,
SiglipEncoderLayer,
)
from tinychat.utils.input_metadata import ActivationBuffer
from transformers.modeling_outputs import BaseModelOutput
from typing import Optional, Tuple, Union
from flash_attn import flash_attn_func
import time
CLIP_RANGE = 5
import awq_inference_engine
class QuantSiglipEncoder(nn.Module):
def __init__(self, module: SiglipEncoder, bsz=64, seqlen=1024):
super().__init__()
self.config = module.config
self.layers = [QuantSiglipEncoderLayer(layer) for layer in module.layers]
self.buffer = ActivationBuffer(module)
self.bsz = bsz
self.seqlen = seqlen
self.buffer.allocate_activation_buffer(self.bsz * self.seqlen)
# Ignore copy
def forward(
self,
inputs_embeds,
attention_mask: Optional[torch.Tensor] = None,
output_attentions: Optional[bool] = None, # dummy
output_hidden_states: Optional[bool] = None,
return_dict: Optional[bool] = None,
) -> Union[Tuple, BaseModelOutput]:
# TODO Find why this code is necessary
# torch.sum(inputs_embeds!=inputs_embeds)
bsz, seqlen, _ = inputs_embeds.shape
if self.bsz != bsz or self.seqlen != seqlen:
self.buffer.allocate_activation_buffer(bsz * seqlen)
self.bsz = bsz
self.seqlen = seqlen
output_hidden_states = (
output_hidden_states
if output_hidden_states is not None
else self.config.output_hidden_states
)
return_dict = (
return_dict if return_dict is not None else self.config.use_return_dict
)
encoder_states = () if output_hidden_states else None
hidden_states = inputs_embeds
for i, encoder_layer in enumerate(self.layers):
if output_hidden_states:
encoder_states = encoder_states + (
hidden_states.reshape(bsz, seqlen, -1),
)
hidden_states = encoder_layer(
hidden_states, self.buffer, attention_mask, bsz, seqlen
)
if output_hidden_states:
encoder_states = encoder_states + (hidden_states.reshape(bsz, seqlen, -1),)
if not return_dict:
return tuple(v for v in [hidden_states, encoder_states] if v is not None)
return BaseModelOutput(
last_hidden_state=hidden_states.reshape(bsz, seqlen, -1),
hidden_states=encoder_states,
attentions=None,
)
class QuantSiglipMLP(nn.Module):
def __init__(self, siglipmlp, init_only=False):
super().__init__()
self.config = siglipmlp.config
self.activation_fn = siglipmlp.activation_fn
self.fc1 = W8A8OF16LinearDynamicInputScale.from_linear(
siglipmlp.fc1, init_only=init_only, fc1=False
)
self.fc2 = W8A8OF16LinearDynamicInputScale.from_linear(
siglipmlp.fc2, init_only=init_only
)
self.invoke_quant = self.invoke_quant_mlp
def invoke_quant_mlp(self, buffer, actfn_output):
awq_inference_engine.invoke_quant(
buffer.quantized_mlp_act_buffer,
actfn_output,
buffer.quantized_scale_buffer,
)
def forward(self, buffer: ActivationBuffer) -> torch.Tensor:
# INT8 in, FP16 out
self.fc1(
buffer.quantized_hidden_states_buffer,
buffer.quantized_scale_buffer,
buffer.fc1_buffer,
)
# Act & quantization
awq_inference_engine.gelu_and_quant(
buffer.quantized_mlp_act_buffer,
buffer.fc1_buffer,
buffer.quantized_scale_buffer,
buffer.tmp,
)
# INT8 in, FP16 out
self.fc2(
buffer.quantized_mlp_act_buffer,
buffer.quantized_scale_buffer,
buffer.in_out_fc2_act_buffer,
)
class QuantSiglipFlashAttention2(nn.Module):
def __init__(
self,
module: SiglipAttention,
init_only=False,
):
super().__init__()
self.config = module.config
self.embed_dim = module.embed_dim
self.num_heads = module.num_heads
self.head_dim = self.embed_dim // self.num_heads
self.qkv_proj = W8A8OF16LinearDynamicInputScale.from_qkv(
module.q_proj, module.k_proj, module.v_proj, init_only=init_only
)
self.out_proj = W8A8OF16LinearDynamicInputScale.from_linear(
module.out_proj, init_only=init_only
)
self.invoke_quant = self.invoke_quant_wo
def invoke_quant_wo(self, buffer, attn_output):
awq_inference_engine.invoke_quant(
buffer.quantized_hidden_states_buffer,
attn_output,
buffer.quantized_scale_buffer,
)
# Adapted from transformers.models.llama.modeling_llama.LlamaFlashAttention2.forward
def forward(
self, buffer: ActivationBuffer, bsz=64, seqlen=1024
) -> Tuple[torch.Tensor, Optional[torch.Tensor], Optional[Tuple[torch.Tensor]]]:
# qkv
self.qkv_proj(
buffer.quantized_hidden_states_buffer,
buffer.quantized_scale_buffer,
buffer.qkv_proj_act_buffer,
)
q, k, v = buffer.qkv_proj_act_buffer.split(
[self.embed_dim, self.embed_dim, self.embed_dim], dim=-1
)
q = q.reshape(bsz, seqlen, self.num_heads, self.head_dim)
k = k.reshape(bsz, seqlen, self.num_heads, self.head_dim)
v = v.reshape(bsz, seqlen, self.num_heads, self.head_dim)
attn_output = flash_attn_func(q, k, v, softmax_scale=None, causal=False)
attn_output = attn_output.reshape(bsz * seqlen, -1)
# FP16 -> int8
self.invoke_quant(buffer, attn_output)
# INT8 in, FP16 out
self.out_proj(
buffer.quantized_hidden_states_buffer,
buffer.quantized_scale_buffer,
buffer.in_out_fc2_act_buffer,
)
class QuantSiglipEncoderLayer(nn.Module):
def __init__(self, module: SiglipEncoderLayer):
super().__init__()
self.embed_dim = module.embed_dim
self.self_attn = QuantSiglipFlashAttention2(module.self_attn)
self.layer_norm1 = RMSNormGeneral(
module.layer_norm1.weight.data,
module.layer_norm1.bias.data,
module.layer_norm1.eps,
True,
).cuda()
self.mlp = QuantSiglipMLP(module.mlp)
self.layer_norm2 = RMSNormGeneral(
module.layer_norm2.weight.data,
module.layer_norm2.bias.data,
module.layer_norm2.eps,
True,
).cuda()
self.quant = self.invoke_quant_norm
def invoke_quant_norm(self, buffer, normfn_output):
awq_inference_engine.invoke_quant(
buffer.quantized_hidden_states_buffer,
normfn_output,
buffer.quantized_scale_buffer,
)
def forward(
self,
hidden_states: torch.Tensor,
buffer: ActivationBuffer,
attention_mask,
bsz,
seqlen,
) -> Tuple[torch.FloatTensor]:
# Attention block
# FP16 in int8 out, layernorm & quantization
residual = hidden_states
self.layer_norm1(
hidden_states.reshape(-1, self.embed_dim),
buffer.quantized_hidden_states_buffer,
buffer.quantized_scale_buffer,
)
# INT8 -> FP16
self.self_attn(buffer, bsz, seqlen)
hidden_states = (
residual.reshape(-1, self.embed_dim) + buffer.in_out_fc2_act_buffer
)
# Fully Connected
residual = hidden_states
# FP16 in int8 out, layernorm & quantization
self.layer_norm2(
hidden_states.reshape(-1, self.embed_dim),
buffer.quantized_hidden_states_buffer,
buffer.quantized_scale_buffer,
)
# INT8 -> FP16
self.mlp(buffer)
hidden_states = (
residual.reshape(-1, self.embed_dim) + buffer.in_out_fc2_act_buffer
)
return hidden_states
class RMSNormGeneral(nn.Module):
"""Root mean square normalization (w/ per-token or per-tensor quant).
Computes x -> w * x / sqrt(E[x^2] + eps) where w is the learned weight.
Refer to https://arxiv.org/abs/1910.07467
"""
def __init__(
self,
weight: torch.tensor,
bias: torch.tensor,
eps: float = 1e-6,
use_per_token_quant: bool = True,
) -> None:
super().__init__()
self.weight = nn.Parameter(weight, requires_grad=False)
self.bias = nn.Parameter(bias, requires_grad=False)
self.variance_epsilon = eps
self.use_per_token_quant = use_per_token_quant
def forward(
self,
x: torch.Tensor,
quantized_hidden_states_buffer: torch.Tensor,
quantized_scale_buffer: torch.Tensor,
quantized_sum_buffer: torch.Tensor = None,
) -> torch.Tensor:
# quantized_sum_buffer is not used, only to keep the consistency of the interface
awq_inference_engine.rms_norm_general(
quantized_hidden_states_buffer,
x,
self.weight.data,
self.bias.data,
quantized_scale_buffer,
self.variance_epsilon,
self.use_per_token_quant,
)