Hi! I'm working on an implementation of inference code for a GPT-like transformer, using a library called ggml and the Rust programming language. I'm having trouble understanding something in the following function:

/// Evaluates the transformer.
 pub fn evaluate(
 &self,
 session: &mut InferenceSession,
 n\_threads: i32,
 input\_tokens: &[TokenId],
 ) {
 let n = input\_tokens.len();
 let n\_past = session.n\_past as i32;

 let Hyperparameters {
 n\_vocab,
 n\_ctx,
 n\_embd,
 n\_mult: \_,
 n\_head,
 n\_layer,
 n\_rot,
 f16\_: \_,
 } = self.hparams;

 let mut buf\_size = 512 \* 1024 \* 1024;
 if session.mem\_per\_token > 0 && session.mem\_per\_token \* n > buf\_size {
 // add 10% to account for ggml object overhead
 buf\_size = (1.1f64 \* session.mem\_per\_token as f64 \* n as f64) as usize;
 };
 let ctx0 = ggml::Context::init(buf\_size);

 let mut gf = ggml::ComputationGraph::new(n\_threads);

 let embd = ctx0.new\_tensor\_1d(ggml::TYPE\_I32, n as i32);
 unsafe { embd.write\_data(bytemuck::cast\_slice(input\_tokens)) };

 let mut input\_layer = ctx0.op\_get\_rows(&self.tok\_embeddings, &embd);
 for il in 0..n\_layer as usize {
 let input\_self\_attention = input\_layer.share();
 let mut current: ggml::Tensor;

 // norm
 {
 current = ctx0.op\_norm(&input\_layer);

 // cur = attention\_norm \* cur
 current = ctx0.op\_mul(
 &ctx0.op\_repeat(&self.layers[il].attention\_norm, ¤t),
 ¤t,
 );
 }

 // self-attention
 {
 let q\_current = ctx0.op\_mul\_mat(&self.layers[il].wq, ¤t);
 let k\_current = ctx0.op\_mul\_mat(&self.layers[il].wk, ¤t);
 let v\_current = ctx0.op\_mul\_mat(&self.layers[il].wv, ¤t);

 // store key and value to memory
 if n >= 1 {
 let k = ctx0.op\_view\_1d(
 &session.memory\_k,
 n as i32 \* n\_embd,
 (session.memory\_k.element\_size() \* n\_embd as usize)
 \* (il \* n\_ctx as usize + n\_past as usize),
 );
 dbg!((il \* n\_ctx as usize + n\_past as usize));

 let v = ctx0.op\_view\_1d(
 &session.memory\_v,
 n as i32 \* n\_embd,
 (session.memory\_v.element\_size() \* n\_embd as usize)
 \* (il \* n\_ctx as usize + n\_past as usize),
 );

 gf.build\_forward\_expand(&ctx0.op\_cpy(&k\_current, &k));
 gf.build\_forward\_expand(&ctx0.op\_cpy(&v\_current, &v));
 }

 // Q = Qcur.contiguous().view(n\_embd/n\_head, n\_head, N).permute(0, 2, 1, 3)
 let q = ctx0.op\_permute(
 &ctx0.op\_rope(
 &ctx0.op\_cpy(
 &q\_current,
 &ctx0.new\_tensor\_3d(ggml::TYPE\_F32, n\_embd / n\_head, n\_head, n as i32),
 ),
 n\_past,
 n\_rot,
 0,
 ),
 0,
 2,
 1,
 3,
 );

 // K = Kmem.view(n\_embd/n\_head, n\_head, n\_past + N).permute(0, 2, 1, 3)
 let k = ctx0.op\_permute(
 &ctx0.op\_rope(
 &ctx0.op\_reshape\_3d(
 &ctx0.op\_view\_1d(
 &session.memory\_k,
 (n\_past + n as i32) \* n\_embd,
 il \* n\_ctx as usize
 \* session.memory\_k.element\_size()
 \* n\_embd as usize,
 ),
 n\_embd / n\_head,
 n\_head,
 n\_past + n as i32,
 ),
 n\_past,
 n\_rot,
 1,
 ),
 0,
 2,
 1,
 3,
 );

 // K \* Q
 let k\_q = ctx0.op\_mul\_mat(&k, &q);

 // KQ\_scaled = KQ / sqrt(n\_embd/n\_head)
 let k\_q\_scaled = ctx0.op\_scale(
 &k\_q,
 &ctx0.new\_f32(1.0 / f32::sqrt(n\_embd as f32 / n\_head as f32)),
 );

 // KQ\_masked = mask\_past(KQ\_scaled)
 let k\_q\_masked = ctx0.op\_diag\_mask\_inf(&k\_q\_scaled, n\_past);

 // KQ = soft\_max(KQ\_masked)
 let k\_q\_soft\_max = ctx0.op\_soft\_max(&k\_q\_masked);

 // V\_trans = Vmem.view(n\_embd/n\_head, n\_head, n\_past + N).permute(1, 2, 0, 3).contiguous()
 let v\_transposed = ctx0.op\_permute(
 &ctx0.op\_reshape\_3d(
 &ctx0.op\_view\_1d(
 &session.memory\_v,
 (n\_past + n as i32) \* n\_embd,
 il \* n\_ctx as usize \* session.memory\_v.element\_size() \* n\_embd as usize,
 ),
 n\_embd / n\_head,
 n\_head,
 n\_past + n as i32,
 ),
 1,
 2,
 0,
 3,
 );

 // KQV = transpose(V) \* KQ\_soft\_max
 let k\_q\_v = ctx0.op\_mul\_mat(&v\_transposed, &k\_q\_soft\_max);

 // KQV\_merged = KQV.permute(0, 2, 1, 3)
 let k\_q\_v\_merged = ctx0.op\_permute(&k\_q\_v, 0, 2, 1, 3);

 // cur = KQV\_merged.contiguous().view(n\_embd, N)
 current = ctx0.op\_cpy(
 &k\_q\_v\_merged,
 &ctx0.new\_tensor\_2d(ggml::TYPE\_F32, n\_embd, n as i32),
 );

 // projection (no bias)
 current = ctx0.op\_mul\_mat(&self.layers[il].wo, ¤t);
 }

 let input\_feed\_forward = ctx0.op\_add(¤t, &input\_self\_attention);

 // feed-forward network
 {
 // norm
 {
 current = ctx0.op\_norm(&input\_feed\_forward);

 // cur = ffn\_norm\*cur
 current = ctx0.op\_mul(
 &ctx0.op\_repeat(&self.layers[il].ffn\_norm, ¤t),
 ¤t,
 );
 }

 let tmp = ctx0.op\_mul\_mat(&self.layers[il].w3, ¤t);

 current = ctx0.op\_mul\_mat(&self.layers[il].w1, ¤t);

 // SILU activation
 current = ctx0.op\_silu(¤t);

 current = ctx0.op\_mul(¤t, &tmp);

 current = ctx0.op\_mul\_mat(&self.layers[il].w2, ¤t);
 }

 current = ctx0.op\_add(¤t, &input\_feed\_forward);

 // input for next layer
 input\_layer = current;
 }

 // norm
 {
 input\_layer = ctx0.op\_norm(&input\_layer);

 // inpL = norm\*inpL
 input\_layer = ctx0.op\_mul(&ctx0.op\_repeat(&self.norm, &input\_layer), &input\_layer);
 }

 // lm\_head
 {
 input\_layer = ctx0.op\_mul\_mat(&self.output, &input\_layer);
 }

 // logits -> probs
 // inpL = ctx0.op\_soft\_max(&inpL);

 // run the computation
 gf.build\_forward\_expand(&input\_layer);
 ctx0.graph\_compute(&mut gf);

 // return result for just the last token
 // SAFETY: yolo
 assert\_eq!(session.last\_logits.len(), n\_vocab as usize);
 unsafe {
 input\_layer.read\_data(
 n\_vocab as usize \* (n - 1) \* std::mem::size\_of::(),
 bytemuck::cast\_slice\_mut(&mut session.last\_logits),
 )
 };

 // Adjust the required memory per token if we didn't know that already
 if session.mem\_per\_token == 0 {
 session.mem\_per\_token = ctx0.used\_mem() / n;
 }

 // Adjust n\_past to new length.
 session.n\_past += input\_tokens.len();
 }
i! 다음 함수에서 무언가를 이해하는 데 문제가 있습니다:/// 트랜스포머를 평가합니다. pub fn evaluate( &self, 세션: &mut 추론 세션, n\_threads: i32, input\_tokens: &[TokenId], ) { let n = input\_tokens.len(); let n\_past = 세션.n\_past as i32; let 하이퍼파라미터 { n\_vocab, n\_ctx, n\_embd, n\_mult: \_, n\_head, n\_layer, n\_rot, f16\_: \_, } = self.hparams; let mut buf\_size = 512 \* 1024 \* 1024; if session.mem\_per\_token > 0 && session.mem\_per\_token \* n > buf\_size { // ggml 객체 오버헤드를 고려하기 위해 10% 추가 buf\_size = (1.1f64 \* session.mem\_per\_token as f64 \* n as f64) as usize; }; let ctx0 = ggml::Context::init(buf\_size); let mut gf = ggml::ComputationGraph::new(n\_threads); let embd = ctx0.new\_tensor\_1d(ggml::TYPE\_I32, n as i32); unsafe { embd.write\_data(bytemuck::cast\_slice(input\_tokens)) }; let mut input\_layer = ctx0.op\_get\_rows(&self.tok\_embeddings, &embd); FOR IL IN 0..N\_레이어 AS USIZE { let input\_self\_attention = input\_layer.share(); let mut current: ggml::Tensor; // norm { current = ctx0.op\_norm(&input\_layer); // cur = attention\_norm \* cur current = ctx0.op\_mul( &ctx0.op\_repeat(&self.layers[il].attention\_norm, ¤t), ¤t, ); } // 셀프 어텐션 { let q\_current = ctx0.op\_mul\_mat(&self.layers[il].wq, ¤t); let k\_current = ctx0.op\_mul\_mat(&self.layers[il].wk, ¤t); let v\_current = ctx0.op\_mul\_mat(&self.layers[il].wv, ¤t); // 키와 값을 메모리에 저장 if n >= 1 { let k = ctx0.op\_view\_1d( &session.memory\_k, n as i32 \* n\_embd, (세션.메모리\_k.요소\_size() \* n\_embd as usize) \* (il \* n\_ctx as usize + n\_past as usize), ); dbg!((il \* n\_ctx as usize + n\_past as usize)); LET V = CTX0.OP\_VIEW\_1D( &session.memory\_v, n을 i32 \* n\_embd, (세션.메모리\_v.요소\_size() \* n\_embd as usize) \* (il \* n\_ctx as usize + n\_past as usize), ); gf.build\_forward\_expand(&ctx0.op\_cpy(&k\_current, &k)); gf.build\_forward\_expand(&ctx0.op\_cpy(&v\_current, &v)); } // Q = Qcur.contiguous().view(n\_embd/n\_head, n\_head, N).permute(0, 2, 1, 3) let q = ctx0.op\_permute( &ctx0.op\_rope( &ctx0.op\_cpy( &q\_current, &ctx0.new\_tensor\_3d(ggml::TYPE\_F32, n\_embd / n\_head, n\_head, n as i32), ), n\_past, n\_rot, 0, ), 0, 2, 1, 3, ); // K = Kmem.view(n\_embd/n\_head, n\_head, n\_past + N).permute(0, 2, 1, 3) let k = ctx0.op\_permute( &ctx0.op\_rope( &ctx0.op\_reshape\_3d( &CTX0.OP\_VIEW\_1D( &SESSION.MEMORY\_K, (n\_past + n as i32) \* n\_embd, IL \* n\_CTX AS USIZE \* 세션.메모리\_k.요소\_size() \* n\_embd를 usize로, ), n\_embd / n\_head, n\_head, n\_past + n을 i32로, ), n\_past, n\_rot, 1, ), 0, 2, 1, 3, ); // K \* Q LET K\_Q = CTX0.OP\_MUL\_MAT(&K, &Q); // KQ\_scaled = KQ / sqrt(n\_embd/n\_head) LET K\_Q\_SCALE = CTX0.OP\_SCALE( &k\_q, &ctx0.new\_f32(1.0 / f32::sqrt(n\_embd as f32 / n\_head as f32))), ); // KQ\_masked = mask\_past(KQ\_scaled) LET K\_Q\_MASKED = CTX0.OP\_DIAG\_MASK\_INF(&K\_Q\_SCALED, N\_PAST); // KQ = soft\_max(KQ\_masked) LET K\_Q\_soft\_max = CTX0.OP\_soft\_max(&k\_Q\_마스크드); // V\_trans = Vmem.view(n\_embd/n\_head, n\_head, n\_past + N).permute(1, 2, 0, 3).contiguous() LET V\_TANSPOSED = CTX0.OP\_PERMUTE( &ctx0.op\_reshape\_3d( &CTX0.OP\_VIEW\_1D( &session.memory\_v, (n\_past + n as i32) \* n\_embd, il \* n\_ctx as usize \* session.memory\_v.element\_size() \* n\_embd as usize, ), n\_embd / n\_head, n\_head, n\_past + n을 i32로, ), 1, 2, 0, 3, ); // KQV = 조옮김(V) \* KQ\_soft\_max LET K\_Q\_V = CTX0.OP\_MUL\_MAT(&V\_Transposed, &K\_Q\_SOFT\_MAX); // KQV\_merged = KQV.permute(0, 2, 1, 3) let k\_q\_v\_merged = ctx0.op\_permute(&k\_q\_v, 0, 2, 1, 3); // cur = KQV\_merged.contiguous().view(n\_embd, N) current = ctx0.op\_cpy( &k\_q\_v\_merged, &ctx0.new\_tensor\_2d(ggml::TYPE\_F32, n\_embd, n as i32), ); // 투영(바이어스 없음) current = ctx0.op\_mul\_mat(&self.layers[il].wo, ¤t); } LET INPUT\_Feed\_FORWARD = CTX0.OP\_ADD(¤T, &INPUT\_SELF\_ATTENTION); // 피드 포워드 네트워크 { // 규범 { current = ctx0.op\_norm(&input\_feed\_forward); // cur = ffn\_norm\*cur current = ctx0.op\_mul( &ctx0.op\_repeat(&self.layers[il].ffn\_norm, ¤t), ¤t, ); } LET TMP = CTX0.OP\_MUL\_MAT(&self.LAYERS[IL].W3, ¤T); current = ctx0.op\_mul\_mat(&self.layers[il].w1, ¤t); // SILU 활성화 current = ctx0.op\_silu(¤t); current = ctx0.op\_mul(¤t, &tmp); current = ctx0.op\_mul\_mat(&self.layers[il].w2, ¤t); } current = ctx0.op\_add(¤t, &input\_feed\_forward); // 다음 레이어에 대한 입력 input\_layer = current; } // 표준 { 입력\_레이어 = CTX0.OP\_NORM(&입력\_레이어); // inpL = norm\*inpL input\_layer = ctx0.op\_mul(&ctx0.op\_repeat(&self.norm, &input\_layer), &input\_layer); } // lm\_head