| 5646 | // ggml_flash_attn_back |
| 5647 | |
| 5648 | struct ggml_tensor * ggml_flash_attn_back( |
| 5649 | struct ggml_context * ctx, |
| 5650 | struct ggml_tensor * q, |
| 5651 | struct ggml_tensor * k, |
| 5652 | struct ggml_tensor * v, |
| 5653 | struct ggml_tensor * d, |
| 5654 | bool masked) { |
| 5655 | GGML_ASSERT(ggml_can_mul_mat(k, q)); |
| 5656 | // TODO: check if vT can be multiplied by (k*qT) |
| 5657 | |
| 5658 | // d shape [D,N,ne2,ne3] |
| 5659 | // q shape [D,N,ne2,ne3] |
| 5660 | // k shape [D,M,kvne2,ne3] |
| 5661 | // v shape [M,D,kvne2,ne3] |
| 5662 | |
| 5663 | const int64_t D = q->ne[0]; |
| 5664 | const int64_t N = q->ne[1]; |
| 5665 | const int64_t M = k->ne[1]; |
| 5666 | const int64_t ne2 = q->ne[2]; |
| 5667 | const int64_t ne3 = q->ne[3]; |
| 5668 | const int64_t kvne2 = k->ne[2]; |
| 5669 | |
| 5670 | GGML_ASSERT(k->ne[0] == D); |
| 5671 | GGML_ASSERT(v->ne[0] == M); |
| 5672 | GGML_ASSERT(v->ne[1] == D); |
| 5673 | GGML_ASSERT(d->ne[0] == D); |
| 5674 | GGML_ASSERT(d->ne[1] == N); |
| 5675 | GGML_ASSERT(k->ne[2] == kvne2); |
| 5676 | GGML_ASSERT(k->ne[3] == ne3); |
| 5677 | GGML_ASSERT(v->ne[2] == kvne2); |
| 5678 | GGML_ASSERT(v->ne[3] == ne3); |
| 5679 | GGML_ASSERT(d->ne[2] == ne2); |
| 5680 | GGML_ASSERT(d->ne[3] == ne3); |
| 5681 | |
| 5682 | GGML_ASSERT(ne2 % kvne2 == 0); |
| 5683 | |
| 5684 | bool is_node = false; |
| 5685 | |
| 5686 | if (q->grad || k->grad || v->grad) { |
| 5687 | // when using this operation (in backwards pass) these grads are set. |
| 5688 | // we don't want to create (big) grad of our result, so is_node is false. |
| 5689 | is_node = false; |
| 5690 | } |
| 5691 | |
| 5692 | // store gradients of q, k and v as continuous tensors concatenated in result. |
| 5693 | // note: v and gradv are actually transposed, i.e. v->ne[0] != D. |
| 5694 | const int64_t elem_q = ggml_nelements(q); |
| 5695 | const int64_t elem_k = ggml_nelements(k); |
| 5696 | const int64_t elem_v = ggml_nelements(v); |
| 5697 | |
| 5698 | enum ggml_type result_type = GGML_TYPE_F32; |
| 5699 | GGML_ASSERT(ggml_blck_size(result_type) == 1); |
| 5700 | const size_t tsize = ggml_type_size(result_type); |
| 5701 | |
| 5702 | const size_t offs_q = 0; |
| 5703 | const size_t offs_k = offs_q + GGML_PAD(elem_q * tsize, GGML_MEM_ALIGN); |
| 5704 | const size_t offs_v = offs_k + GGML_PAD(elem_k * tsize, GGML_MEM_ALIGN); |
| 5705 | const size_t end = offs_v + GGML_PAD(elem_v * tsize, GGML_MEM_ALIGN); |
no test coverage detected