use crate::models::gpt2::cpu::{Gpt2Model, Gpt2Params};
use crate::ops::{
BatchedMultiqueryAttention, BatchedMultiqueryAttentionParams, LayerNorm, Unary, UnaryOp,
};
use naga_oil::compose::ComposerError;
use wgcore::kernel::KernelInvocationQueue;
use wgcore::tensor::{GpuMatrix, GpuScalar, GpuVector};
use wgcore::Shader;
use wgebra::linalg::{Gemv, OpAssign, OpAssignVariant};
use wgpu::{BufferUsages, Device};
pub struct Gpt2State {
memory_q: GpuVector<f32>,
memory_att: GpuMatrix<f32>,
layer_input: GpuVector<f32>,
curr_768: GpuVector<f32>,
curr_768_b: GpuVector<f32>,
curr_2304: GpuVector<f32>,
curr_3072: GpuVector<f32>,
curr_vocab: GpuVector<f32>,
logits_readback: GpuVector<f32>,
attn_params: GpuScalar<BatchedMultiqueryAttentionParams>,
}
impl Gpt2State {
pub fn new(device: &Device, config: &Gpt2Params) -> Self {
const STORAGE: BufferUsages = BufferUsages::STORAGE;
const UNIFORM: BufferUsages = BufferUsages::UNIFORM;
Self {
memory_q: GpuVector::uninit(device, config.n_embd as u32, STORAGE),
memory_att: GpuMatrix::uninit(
device,
config.n_seq as u32,
config.n_head as u32,
STORAGE,
),
layer_input: GpuVector::uninit(device, config.n_embd as u32, STORAGE),
curr_768: GpuVector::uninit(device, config.n_embd as u32, STORAGE),
curr_768_b: GpuVector::uninit(device, config.n_embd as u32, STORAGE),
curr_2304: GpuVector::uninit(device, config.attn_b as u32, STORAGE),
curr_3072: GpuVector::uninit(device, config.ff_len as u32, STORAGE),
curr_vocab: GpuVector::uninit(
device,
config.n_vocab as u32,
STORAGE | BufferUsages::COPY_SRC,
),
attn_params: GpuScalar::uninit(device, UNIFORM | BufferUsages::COPY_DST),
logits_readback: GpuVector::uninit(
device,
config.n_vocab as u32,
BufferUsages::COPY_DST | BufferUsages::MAP_READ,
),
}
}
pub fn logits_readback(&self) -> &GpuVector<f32> {
&self.logits_readback
}
pub fn logits(&self) -> &GpuVector<f32> {
&self.curr_vocab
}
pub fn attn_params(&self) -> &GpuScalar<BatchedMultiqueryAttentionParams> {
&self.attn_params
}
}
pub struct Gpt2LayerWeights {
ln_1_g: GpuVector<f32>,
ln_1_b: GpuVector<f32>,
ln_2_g: GpuVector<f32>,
ln_2_b: GpuVector<f32>,
c_attn_attn_w: GpuMatrix<f32>,
c_attn_attn_b: GpuVector<f32>,
c_attn_proj_w: GpuMatrix<f32>,
c_attn_proj_b: GpuVector<f32>,
key_cache: GpuMatrix<f32>,
value_cache: GpuMatrix<f32>,
c_mlp_fc_w: GpuMatrix<f32>,
c_mlp_fc_b: GpuVector<f32>,
c_mlp_proj_w: GpuMatrix<f32>,
c_mlp_proj_b: GpuVector<f32>,
}
pub struct Gpt2Weights {
ln_f_g: GpuVector<f32>,
ln_f_b: GpuVector<f32>,
wte: GpuMatrix<f32>, wpe: GpuMatrix<f32>, lm_head: GpuMatrix<f32>,
layers: Vec<Gpt2LayerWeights>,
}
impl Gpt2Weights {
pub fn from_ram(device: &Device, w: &Gpt2Model) -> Self {
const STORAGE: BufferUsages = BufferUsages::STORAGE;
Self {
ln_f_g: GpuVector::init(device, &w.ln_f_g, STORAGE),
ln_f_b: GpuVector::init(device, &w.ln_f_b, STORAGE),
wte: GpuMatrix::init(device, &w.wte, STORAGE),
wpe: GpuMatrix::init(device, &w.wpe, STORAGE),
lm_head: GpuMatrix::init(device, &w.lm_head, STORAGE),
layers: w
.layers
.iter()
.map(|l| Gpt2LayerWeights {
ln_1_g: GpuVector::init(device, &l.ln_1_g, STORAGE),
ln_1_b: GpuVector::init(device, &l.ln_1_b, STORAGE),
ln_2_g: GpuVector::init(device, &l.ln_2_g, STORAGE),
ln_2_b: GpuVector::init(device, &l.ln_2_b, STORAGE),
c_attn_attn_w: GpuMatrix::init(device, &l.c_attn_attn_w, STORAGE),
c_attn_attn_b: GpuVector::init(device, &l.c_attn_attn_b, STORAGE),
c_attn_proj_w: GpuMatrix::init(device, &l.c_attn_proj_w, STORAGE),
c_attn_proj_b: GpuVector::init(device, &l.c_attn_proj_b, STORAGE),
key_cache: GpuMatrix::init(device, &l.key_cache, STORAGE),
value_cache: GpuMatrix::init(device, &l.value_cache, STORAGE),
c_mlp_fc_w: GpuMatrix::init(device, &l.c_mlp_fc_w, STORAGE),
c_mlp_fc_b: GpuVector::init(device, &l.c_mlp_fc_b, STORAGE),
c_mlp_proj_w: GpuMatrix::init(device, &l.c_mlp_proj_w, STORAGE),
c_mlp_proj_b: GpuVector::init(device, &l.c_mlp_proj_b, STORAGE),
})
.collect(),
}
}
}
pub struct Gpt2 {
layernorm: LayerNorm,
gelu: Unary,
matmul: Gemv,
attn: BatchedMultiqueryAttention,
copy_from: OpAssign,
mul_assign: OpAssign,
add_assign: OpAssign,
}
impl Gpt2 {
pub fn new(device: &Device) -> Result<Self, ComposerError> {
Ok(Self {
layernorm: LayerNorm::from_device(device)?,
gelu: Unary::new(device, UnaryOp::Gelu)?,
matmul: Gemv::from_device(device)?,
attn: BatchedMultiqueryAttention::from_device(device)?,
copy_from: OpAssign::new(device, OpAssignVariant::Copy)?,
mul_assign: OpAssign::new(device, OpAssignVariant::Mul)?,
add_assign: OpAssign::new(device, OpAssignVariant::Add)?,
})
}
pub fn queue<'a>(
&'a self,
queue: &mut KernelInvocationQueue<'a>,
state: &Gpt2State,
weights: &Gpt2Weights,
config: &Gpt2Params,
embd: u32,
pos: u32,
) {
self.copy_from
.queue(queue, &state.layer_input, weights.wte.column(embd));
self.add_assign
.queue(queue, &state.layer_input, weights.wpe.column(pos));
for layer in &weights.layers {
{
self.layernorm
.queue(queue, &state.curr_768, &state.layer_input);
self.mul_assign.queue(queue, &state.curr_768, &layer.ln_1_g);
self.add_assign.queue(queue, &state.curr_768, &layer.ln_1_b);
}
{
self.matmul.queue(
queue,
&state.curr_2304,
&layer.c_attn_attn_w,
&state.curr_768,
);
self.add_assign
.queue(queue, &state.curr_2304, &layer.c_attn_attn_b);
}
{
let k_cache = layer.key_cache.column(pos);
let v_cache = layer.value_cache.column(pos);
self.copy_from.queue(
queue,
&state.memory_q,
state.curr_2304.rows(0, config.n_embd as u32),
);
self.copy_from.queue(
queue,
k_cache,
state
.curr_2304
.rows(config.n_embd as u32, config.n_embd as u32),
);
self.copy_from.queue(
queue,
v_cache,
state
.curr_2304
.rows(2 * config.n_embd as u32, config.n_embd as u32),
);
self.attn.queue(
queue,
&state.attn_params,
&state.memory_q,
&layer.key_cache,
&layer.value_cache,
&state.memory_att,
&state.curr_768,
);
}
{
self.matmul.queue(
queue,
&state.curr_768_b,
&layer.c_attn_proj_w,
&state.curr_768,
);
self.add_assign
.queue(queue, &state.curr_768_b, &layer.c_attn_proj_b);
}
self.add_assign
.queue(queue, &state.curr_768_b, &state.layer_input);
self.copy_from
.queue(queue, &state.layer_input, &state.curr_768_b);
{
{
self.layernorm
.queue(queue, &state.curr_768, &state.curr_768_b);
self.mul_assign.queue(queue, &state.curr_768, &layer.ln_2_g);
self.add_assign.queue(queue, &state.curr_768, &layer.ln_2_b);
}
self.matmul
.queue(queue, &state.curr_3072, &layer.c_mlp_fc_w, &state.curr_768);
self.add_assign
.queue(queue, &state.curr_3072, &layer.c_mlp_fc_b);
self.gelu
.queue(queue, &state.curr_3072, &state.curr_3072, None);
self.matmul.queue(
queue,
&state.curr_768,
&layer.c_mlp_proj_w,
&state.curr_3072,
);
self.add_assign
.queue(queue, &state.curr_768, &layer.c_mlp_proj_b);
}
self.add_assign
.queue(queue, &state.layer_input, &state.curr_768);
}
{
self.layernorm
.queue(queue, &state.curr_768, &state.layer_input);
self.mul_assign
.queue(queue, &state.curr_768, &weights.ln_f_g);
self.add_assign
.queue(queue, &state.curr_768, &weights.ln_f_b);
}
self.matmul
.queue(queue, &state.curr_vocab, &weights.lm_head, &state.curr_768);
}
}