diff options
author | Laurent Mazare <laurent.mazare@gmail.com> | 2024-05-18 19:18:59 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-18 19:18:59 +0200 |
commit | 7ebc3548e19fb8d40940fa2315b3f817058e7e96 (patch) | |
tree | e8097869ef0b6f8db1a9091ef2f7df078e013cc7 /candle-transformers | |
parent | eefc1c77ef00b74e1f8c6ac4e217dfbdbd419eff (diff) | |
download | candle-7ebc3548e19fb8d40940fa2315b3f817058e7e96.tar.gz candle-7ebc3548e19fb8d40940fa2315b3f817058e7e96.tar.bz2 candle-7ebc3548e19fb8d40940fa2315b3f817058e7e96.zip |
Use flash-attn in gemma. (#2195)
* Use flash-attn in gemma.
* Fix flash-attn for head dim 256.
Diffstat (limited to 'candle-transformers')
-rw-r--r-- | candle-transformers/src/models/gemma.rs | 62 |
1 files changed, 44 insertions, 18 deletions
diff --git a/candle-transformers/src/models/gemma.rs b/candle-transformers/src/models/gemma.rs index 3bde88b4..1cfef59e 100644 --- a/candle-transformers/src/models/gemma.rs +++ b/candle-transformers/src/models/gemma.rs @@ -73,13 +73,6 @@ struct RotaryEmbedding { cos: Tensor, } -fn rotate_half(xs: &Tensor) -> Result<Tensor> { - let last_dim = xs.dim(D::Minus1)?; - let xs1 = xs.narrow(D::Minus1, 0, last_dim / 2)?; - let xs2 = xs.narrow(D::Minus1, last_dim / 2, last_dim - last_dim / 2)?; - Tensor::cat(&[&xs2.neg()?, &xs1], D::Minus1) -} - impl RotaryEmbedding { fn new(dtype: DType, cfg: &Config, dev: &Device) -> Result<Self> { let dim = cfg.head_dim; @@ -94,7 +87,6 @@ impl RotaryEmbedding { .to_dtype(dtype)? .reshape((max_seq_len, 1))?; let freqs = t.matmul(&inv_freq)?; - let freqs = Tensor::cat(&[&freqs, &freqs], D::Minus1)?; Ok(Self { sin: freqs.sin()?, cos: freqs.cos()?, @@ -110,10 +102,8 @@ impl RotaryEmbedding { let (_b_sz, _h, seq_len, _n_embd) = q.dims4()?; let cos = self.cos.narrow(0, seqlen_offset, seq_len)?; let sin = self.sin.narrow(0, seqlen_offset, seq_len)?; - let cos = cos.unsqueeze(0)?.unsqueeze(0)?; // (1, 1, seq_len, dim) - let sin = sin.unsqueeze(0)?.unsqueeze(0)?; // (1, 1, seq_len, dim) - let q_embed = (q.broadcast_mul(&cos)? + rotate_half(q)?.broadcast_mul(&sin))?; - let k_embed = (k.broadcast_mul(&cos)? + rotate_half(k)?.broadcast_mul(&sin))?; + let q_embed = candle_nn::rotary_emb::rope(&q.contiguous()?, &cos, &sin)?; + let k_embed = candle_nn::rotary_emb::rope(&k.contiguous()?, &cos, &sin)?; Ok((q_embed, k_embed)) } } @@ -163,10 +153,16 @@ struct Attention { head_dim: usize, rotary_emb: Arc<RotaryEmbedding>, kv_cache: Option<(Tensor, Tensor)>, + use_flash_attn: bool, } impl Attention { - fn new(rotary_emb: Arc<RotaryEmbedding>, cfg: &Config, vb: VarBuilder) -> Result<Self> { + fn new( + rotary_emb: Arc<RotaryEmbedding>, + use_flash_attn: bool, + cfg: &Config, + vb: VarBuilder, + ) -> Result<Self> { let hidden_sz = cfg.hidden_size; let num_heads = cfg.num_attention_heads; let num_kv_heads = cfg.num_key_value_heads; @@ -188,6 +184,7 @@ impl Attention { head_dim, rotary_emb, kv_cache: None, + use_flash_attn, }) } @@ -231,7 +228,14 @@ impl Attention { let value_states = crate::utils::repeat_kv(value_states, self.num_kv_groups)?.contiguous()?; - let attn_output = { + let attn_output = if self.use_flash_attn { + // flash-attn expects (b_sz, seq_len, nheads, head_dim) + let q = query_states.transpose(1, 2)?; + let k = key_states.transpose(1, 2)?; + let v = value_states.transpose(1, 2)?; + let scale = 1f32 / (self.head_dim as f32).sqrt(); + flash_attn(&q, &k, &v, scale, attention_mask.is_some())?.transpose(1, 2)? + } else { let scale = 1f64 / f64::sqrt(self.head_dim as f64); let attn_weights = (query_states.matmul(&key_states.transpose(2, 3)?)? * scale)?; @@ -253,6 +257,22 @@ impl Attention { } } +#[cfg(feature = "flash-attn")] +fn flash_attn( + q: &Tensor, + k: &Tensor, + v: &Tensor, + softmax_scale: f32, + causal: bool, +) -> Result<Tensor> { + candle_flash_attn::flash_attn(q, k, v, softmax_scale, causal) +} + +#[cfg(not(feature = "flash-attn"))] +fn flash_attn(_: &Tensor, _: &Tensor, _: &Tensor, _: f32, _: bool) -> Result<Tensor> { + unimplemented!("compile with '--features flash-attn'") +} + #[derive(Debug, Clone)] struct DecoderLayer { self_attn: Attention, @@ -262,8 +282,13 @@ struct DecoderLayer { } impl DecoderLayer { - fn new(rotary_emb: Arc<RotaryEmbedding>, cfg: &Config, vb: VarBuilder) -> Result<Self> { - let self_attn = Attention::new(rotary_emb, cfg, vb.pp("self_attn"))?; + fn new( + rotary_emb: Arc<RotaryEmbedding>, + use_flash_attn: bool, + cfg: &Config, + vb: VarBuilder, + ) -> Result<Self> { + let self_attn = Attention::new(rotary_emb, use_flash_attn, cfg, vb.pp("self_attn"))?; let mlp = MLP::new(cfg, vb.pp("mlp"))?; let input_layernorm = RmsNorm::new(cfg.hidden_size, cfg.rms_norm_eps, vb.pp("input_layernorm"))?; @@ -312,7 +337,7 @@ pub struct Model { } impl Model { - pub fn new(cfg: &Config, vb: VarBuilder) -> Result<Self> { + pub fn new(use_flash_attn: bool, cfg: &Config, vb: VarBuilder) -> Result<Self> { let vb_m = vb.pp("model"); let embed_tokens = candle_nn::embedding(cfg.vocab_size, cfg.hidden_size, vb_m.pp("embed_tokens"))?; @@ -320,7 +345,8 @@ impl Model { let mut layers = Vec::with_capacity(cfg.num_hidden_layers); let vb_l = vb_m.pp("layers"); for layer_idx in 0..cfg.num_hidden_layers { - let layer = DecoderLayer::new(rotary_emb.clone(), cfg, vb_l.pp(layer_idx))?; + let layer = + DecoderLayer::new(rotary_emb.clone(), use_flash_attn, cfg, vb_l.pp(layer_idx))?; layers.push(layer) } let norm = RmsNorm::new(cfg.hidden_size, cfg.rms_norm_eps, vb_m.pp("norm"))?; |