๐ ์ ์ฒด ๊ตฌ์กฐ ์์ฝ
์ด ์ฝ๋๋ ggml๋ก ๊ฐ๋จํ ํ๋ ฌ ๊ณฑ์ (matmul)์ ์ํํ๋ ์์ ์ ๋๋ค:
- CPU ๋๋ GPU(Metal / CUDA) backend์์ ์ฐ์ฐ ์ํ
- ggml ๊ณ์ฐ ๊ทธ๋ํ ๊ตฌ์ฑ โ ์คํ โ ๊ฒฐ๊ณผ ํ์ธ
- ggml์ “๊ทธ๋ํ ๊ธฐ๋ฐ ์ฐ์ฐ ๋ชจ๋ธ” ๊ตฌ์กฐ๋ฅผ ๋ณด์ฌ์ฃผ๋ ์ข์ ์์
๐บ๏ธ ๊ตฌ์กฐ ๋จ๊ณ๋ณ ๋ถ์
1๏ธโฃ ์ค๋น
#include "ggml.h"
#include "ggml-alloc.h"
#include "ggml-backend.h"
- ggml core, ๋ฉ๋ชจ๋ฆฌ ํ ๋น๊ธฐ, backend API ์ฌ์ฉ
2๏ธโฃ ๋ชจ๋ธ ์ ์
struct simple_model {
struct ggml_tensor* a{};
struct ggml_tensor* b{};
ggml_backend_t backend = nullptr;
ggml_backend_buffer_t buffer{};
struct ggml_context* ctx{};
};
- simple_model ๊ตฌ์กฐ์ฒด์ 2๊ฐ์ ํ ์ a, b ์ ์ธ
- backend ์ค์ (CPU / CUDA / Metal)
- backend buffer ์ฌ์ฉ (a, b ๋ฐ์ดํฐ๋ฅผ ์ ์ฅ)
- context๋ ggml์์ ํ ์ ๋ฉํ ์ ๋ณด, ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ๋ฅผ ๋ด๋น
3๏ธโฃ ๋ฐ์ดํฐ ์ค๋น
float matrix_A[4 * 2] = { ... };
float matrix_B[3 * 2] = { ... };
- matrix_A: (4×2) matrix
- matrix_B: (3×2) matrix โ ๋ด๋ถ์์ transpose๋์ด ๊ณฑํด์ง
4๏ธโฃ Backend ์ด๊ธฐํ
#ifdef GGML_USE_CUDA
model.backend = ggml_backend_cuda_init(0);
#endif
#ifdef GGML_USE_METAL
model.backend = ggml_backend_metal_init();
#endif
if (!model.backend) {
model.backend = ggml_backend_cpu_init();
}
- CUDA โ Metal โ CPU ์์ผ๋ก backend ์ด๊ธฐํ
- llama.cpp๋ ๋น์ทํ ๊ตฌ์กฐ (๋ค์ํ backend ์ง์)
5๏ธโฃ ggml context ์์ฑ + ํ ์ ์์ฑ
ggml_init_params params{...};
model.ctx = ggml_init(params);
model.a = ggml_new_tensor_2d(model.ctx, GGML_TYPE_F32, 2, 4);
model.b = ggml_new_tensor_2d(model.ctx, GGML_TYPE_F32, 2, 3);
- ggml context ์์ฑ โ ํ ์ ์์ฑ
ggml_new_tensor_2d
๋ก 2D tensor ์์ฑ (shape = cols, rows ์ฃผ์)
6๏ธโฃ Backend buffer ์ฌ์ฉ
model.buffer = ggml_backend_alloc_ctx_tensors(model.ctx, model.backend);
ggml_backend_tensor_set(model.a, a, ...);
ggml_backend_tensor_set(model.b, b, ...);
- backend buffer์ ํ ์ ๋ฐ์ดํฐ๋ฅผ ์ง์ ์ ๋ก๋
- CPU โ GPU ๋ฉ๋ชจ๋ฆฌ ๋ณต์ฌ ์ง์ ์ปจํธ๋กค โ llama.cpp์ ๋์ผํ ์ค๊ณ ์ฒ ํ
7๏ธโฃ ๊ณ์ฐ ๊ทธ๋ํ ๊ตฌ์ฑ
ggml_context* ctx0 = ggml_init(params0);
ggml_cgraph* gf = ggml_new_graph(ctx0);
ggml_tensor* result = ggml_mul_mat(ctx0, model.a, model.b);
ggml_build_forward_expand(gf, result);
- ๋ณ๋์ temporay context ์์ฑ โ ๊ณ์ฐ ๊ทธ๋ํ ๊ตฌ์ฑ
ggml_mul_mat
: ํ๋ ฌ ๊ณฑ ์ฐ์ฐ ๋ ธ๋ ์์ฑ- ๊ทธ๋ํ ๋น๋ ๋จ๊ณ โ llama.cpp์์๋ ํ์
8๏ธโฃ ๋ฉ๋ชจ๋ฆฌ ์์ฝ + ๊ทธ๋ํ ์คํ
ggml_gallocr_alloc_graph(allocr, gf);
ggml_backend_graph_compute(model.backend, gf);
- ๋ฉ๋ชจ๋ฆฌ ํ ๋น๊ธฐ(allocator)๋ก ๊ทธ๋ํ ์ต์ ํ ์คํ
- backend์์ ๊ทธ๋ํ ์คํ โ CPU๋ GPU๋ ๋์ผํ API ์ฌ์ฉ (llama.cpp์์๋ ๋์ผ)
9๏ธโฃ ๊ฒฐ๊ณผ ๊ฐ์ ธ์ค๊ธฐ + ์ถ๋ ฅ
ggml_backend_tensor_get(result, out_data.data(), ...);
- backend ๋ฉ๋ชจ๋ฆฌ โ CPU ๋ฉ๋ชจ๋ฆฌ๋ก ๊ฒฐ๊ณผ ๋ณต์ฌ
- ๊ฒฐ๊ณผ ํ๋ ฌ ์ถ๋ ฅ
10๏ธโฃ ๋ง๋ฌด๋ฆฌ ์ ๋ฆฌ
ggml_gallocr_free(allocr);
ggml_free(model.ctx);
ggml_backend_buffer_free(model.buffer);
ggml_backend_free(model.backend);
- ๋ฉ๋ชจ๋ฆฌ ๋ฐ backend clean-up
๐ฉ ํต์ฌ ํฌ์ธํธ
โ
ggml๋ ๊ทธ๋ํ ๊ธฐ๋ฐ ์ฐ์ฐ์ ์ฌ์ฉ
โ
๋ฉ๋ชจ๋ฆฌ ์ปจํธ๋กค๊ณผ backend ์ ์ด๋ฅผ ์ง์ ์ ์ผ๋ก ๋
ธ์ถ
โ
llama.cpp์ ๊ตฌ์กฐ์ ์ผ๋ก ๋์ผ:
- llama.cpp๋
ggml_graph_compute
์ฌ์ฉ - backend abstraction ์ฌ์ฉ
- memory ๊ด๋ฆฌ explicit
โ on-device ์ต์ ํ์ ๋งค์ฐ ์ ๋ฆฌํ ๊ตฌ์กฐ
๐ ์ดํ
- ๋งค์ฐ ์ข์ ggml ์ํ
- llama.cpp์ ๋ด๋ถ ๊ตฌ์กฐ ์ดํด์ ๋ฑ ์ ํฉ
- “C/C++ ๊ธฐ๋ฐ + ๊ทธ๋ํ ๊ธฐ๋ฐ + backend abstraction” โ llama.cpp๊ฐ ์๋ฒ ๋๋์ ๊ฐํ ์ด์ ๊ทธ๋๋ก ๋ณด์ฌ์ค
๐ ์ถ๊ฐ๋ก ๋ณผ๋งํ ํ์ฅ ๋ฐฉํฅ
1๏ธโฃ ggml_compute_forward vs backend_graph_compute ์ฐจ์ด โ CPU ์ ์ฉ vs multi-backend ์ง์ ์ฐจ์ด
2๏ธโฃ ggml-alloc์ ์ญํ โ runtime ๋ฉ๋ชจ๋ฆฌ ์ต์ ํ
3๏ธโฃ gguf ํ์ผ ๋ก๋ฉ โ llama.cpp์์๋ gguf โ ggml_tensor ๊ตฌ์ฑ โ ggml_graph ์คํ ํ๋ฆ
๐บ๏ธ ggml-simple.cpp vs llama.cpp ๊ตฌ์กฐ ๋น๊ต
๐๏ธ 1๏ธโฃ ๊ณตํต ๊ธฐ๋ณธ ๊ตฌ์กฐ
๋จ๊ณ | ggml-simple.cpp | llama.cpp |
---|---|---|
Backend ์ด๊ธฐํ | CUDA/Metal/CPU backend ์ ํ | ๋์ผ (llama.cpp๋ backend layer ์กด์ฌ) |
ggml_context ์์ฑ | ggml_init(params) | ggml_init(params) (llama.cpp ๋ด๋ถ llama_init_from_file ) |
Tensor ๊ตฌ์ฑ | ggml_new_tensor_2d ์ง์ ํธ์ถ | ๋ชจ๋ธ ๋ก๋ฉ์ gguf โ tensor ์๋ ๊ตฌ์ฑ |
๋ฐ์ดํฐ ์ ๋ก๋ | ggml_backend_tensor_set ์๋ ์
๋ก๋ | gguf ๋ก๋ฉ์ ์๋ tensor ์ด๊ธฐํ + backend buffer ์ ๋ก๋ |
๊ณ์ฐ ๊ทธ๋ํ ๊ตฌ์ฑ | ggml_mul_mat โ ggml_build_forward_expand | llama_decode_internal ๋ด์์ ์ฌ๋ฌ ggml_xxx ์ฐ์ฐ ํธ์ถ ํ build |
๋ฉ๋ชจ๋ฆฌ ํ ๋น ์ต์ ํ | ggml_gallocr_alloc_graph | llama_batch_decode ์ ๋ด๋ถ alloc ์ฌ์ฉ |
๊ทธ๋ํ ์คํ | ggml_backend_graph_compute | ggml_backend_graph_compute (llama.cpp๋ ๋์ผ ํธ์ถ) |
๊ฒฐ๊ณผ ์ถ์ถ | ggml_backend_tensor_get | llama_decode_internal ์์ logits ์ถ์ถ์ ์ฌ์ฉ |
๐ผ๏ธ ๊ตฌ์กฐ ํ๋ฆ๋ ์๊ฐํ
๐ ggml-simple.cpp
[main]
โ
[backend init] โ [ggml_init]
โ
[create tensor A, B] โ [upload tensor data]
โ
[build graph: ggml_mul_mat]
โ
[alloc graph memory]
โ [compute graph] โ [get result tensor]
๐ llama.cpp
(inference ๊ฒฝ๋ก)
[llama_init_from_file]
โ
[backend init] โ [ggml_init]
โ
[load model.gguf โ create all ggml_tensor]
โ
[upload tensor data to backend buffer]
โ
[user calls llama_decode or llama_batch_decode]
โ
[llama_decode_internal builds ggml_graph]
โ
[alloc graph memory (alloc + scratch)]
โ
[compute graph (ggml_backend_graph_compute)]
โ
[extract logits tensor โ tokenizer / output]
๐ ํต์ฌ ์ฐจ์ด์
โ
ggml-simple.cpp
๋ ์๋์ผ๋ก ํ
์ ๋ง๋ค๊ณ ๊ทธ๋ํ ๊ตฌ์ฑ
โ
llama.cpp๋ gguf ๊ธฐ๋ฐ์ผ๋ก ํ
์ ์๋ ๊ตฌ์ฑ + LLM ์ํคํ
์ฒ(Attention/MLP/Norm ๋ฑ) ๊ตฌ์ฑ
- llama.cpp ๋ด๋ถ์ ํต์ฌ ๊ทธ๋ํ๋:
- ggml_mul_mat
- ggml_norm
- ggml_silu
- ggml_repeat
- ggml_add / ggml_mul / ggml_reshape ๋ฑ
โ ์ด ๋ชจ๋ ๋ ธ๋๋ค์ดggml_cgraph
๋ก ๋น๋๋๊ณ ์คํ๋จ โ ์ง๊ธ ์ฌ๋ ค์ฃผ์ ์ฝ๋ ํ๋ฆ๊ณผ ๊ฑฐ์ ๋์ผํ ๊ตฌ์กฐ
๐ ์ ๋ฆฌ
- ์ง๊ธ ์ฌ๋ ค์ฃผ์
ggml-simple.cpp
๋ llama.cpp ๊ตฌ์กฐ ์ดํด์ ๋งค์ฐ ์ข์ ์ํ์ โ llama.cpp ๋ด๋ถ๋ ๊ฒฐ๊ตญ ggml_graph๋ฅผ ๊ตฌ์ฑํด ์คํํ๋ ๊ตฌ์กฐ - llama.cpp๋:
- model.gguf ๋ก๋ ์ โ tensor ๊ตฌ์ฑ
- llama_decode ํธ์ถ ์ โ ggml_graph ๊ตฌ์ฑ
- ggml_backend_graph_compute๋ก ์คํ
- ์ด์์ฑ + ์ต์ ํ ํฌ์ธํธ๋ ๋์ผํ๊ฒ ggml ๊ตฌ์กฐ์ ๊ธฐ๋ฐ
๐จ ์ถ์ฒ ํ์ต ์์
1๏ธโฃ ggml-simple.cpp
์์ ggml_mul_mat โ โ MLP Layer ๊ตฌ์ฑ๋ ์ฐ์ต
2๏ธโฃ llama.cpp์ llama_decode_internal
ํจ์ ๋ถ์
3๏ธโฃ gguf
ํ์ผ ๊ตฌ์กฐ ๋ถ์ (gguf = LLM weights + arch config + metadata)
4๏ธโฃ llama.cpp์ ์ปค์คํ
ggml ์ฐ์ฐ ์ถ๊ฐ ์คํ
๐บ๏ธ llama.cpp ์ต์ (2025) llama_decode_internal
๊ตฌ์กฐ ํ๋ฆ
1๏ธโฃ llama_init_from_file
- gguf ๋ชจ๋ธ ํ์ผ ๋ก๋
- ๋ชจ๋ ggml_tensor ์์ฑ (weights, embeddings, norms ๋ฑ)
- backend init + backend buffer alloc + tensor data ์ ๋ก๋
- โ ๊ธฐ๋ณธ์ ์ผ๋ก
ggml_new_tensor_xd
+ggml_backend_tensor_set
์ฌ์ฉ๋จ โggml-simple.cpp
์ ๋์ผ
2๏ธโฃ llama_decode_internal ํธ์ถ
- ํต์ฌ LLM “forward pass” ์ํ
[llama_decode_internal]
โ
[ggml_init graph context]
โ
[ggml_cgraph* gf = ggml_new_graph(ctx)]
โ
[build graph for N tokens โ 1 layer์ฉ loop]
3๏ธโฃ Per-layer graph ๊ตฌ์ฑ
For each Transformer layer:
[ggml_rms_norm] โ Norm
โ
[ggml_mul_mat] Q_proj โ Q
[ggml_mul_mat] K_proj โ K
[ggml_mul_mat] V_proj โ V
โ
[ggml_rope] apply rotary positional embedding to Q,K
โ
[ggml_mul_mat] Q x K^T โ attention scores
[ggml_soft_max] attention scores โ weights
[ggml_mul_mat] weights x V โ attention output
โ
[ggml_add] residual connection
โ
[ggml_rms_norm] โ Norm
โ
[ggml_mul_mat] FFN_1 (intermediate proj)
[ggml_silu] activation
[ggml_mul] gated activation
[ggml_mul_mat] FFN_2 (final proj)
โ
[ggml_add] residual connection
โ Transformer layer 1๊ฐ ๋น ์์ ๊ฐ์ ggml node ๊ทธ๋ํ ๊ตฌ์ฑ
4๏ธโฃ ์ ์ฒด Graph ์ต์ข ๊ตฌ์ฑ
[embedding lookup]
โ
[layer loop: N layers โ ggml nodes push]
โ
[ggml_norm + projection to logits]
โ
[ggml_cgraph build complete โ ggml_build_forward_expand(gf, final_logits)]
5๏ธโฃ ๊ทธ๋ํ ์คํ
ggml_backend_graph_compute(backend, gf);
- ๋ฐ๋ก ์๊น
ggml-simple.cpp
์ ๋์ผํ ํธ์ถ - backend(CPU, CUDA, Metal ๋ฑ)์ ๋ฐ๋ผ ์ต์ ํ ์คํ
6๏ธโฃ ๊ฒฐ๊ณผ ์ถ์ถ
ggml_backend_tensor_get(final_logits_tensor, ...)
- logits ๊ฒฐ๊ณผ ์ถ์ถ ํ softmax / sampling โ output token ๊ฒฐ์
๐ ์ ๋ฆฌ
ggml-simple.cpp | llama.cpp ๋ด๋ถ ๊ตฌ์กฐ |
---|---|
ggml_mul_mat | ggml_mul_mat (Q_proj, K_proj, V_proj, FFN ๋ฑ) |
ggml_build_forward_expand | ggml_build_forward_expand |
ggml_backend_graph_compute | ggml_backend_graph_compute |
tensor ์๋ ์ ๋ ฅ | gguf๋ก ์๋ ๋ก๋ ํ tensor ๊ตฌ์ฑ |
matmul ๊ฒฐ๊ณผ ์ถ๋ ฅ | logits ๊ฒฐ๊ณผ ์ถ๋ ฅ |
๐ฉ ๊ฒฐ๋ก
โ
llama.cpp๋ ๊ฒฐ๊ตญ ggml_graph ๊ธฐ๋ฐ์ผ๋ก ๋ชจ๋ LLM forward pass๋ฅผ ๊ตฌํ
โ
์๊น ์ฌ๋ ค์ฃผ์ ggml-simple.cpp
๊ฐ ๊ตฌ์กฐ์ ์ผ๋ก ๊ฑฐ์ ๋์ผ:
- Backend ์ด๊ธฐํ โ Tensor ๊ตฌ์ฑ โ Graph ๊ตฌ์ฑ โ Graph ์คํ โ ๊ฒฐ๊ณผ ์ถ๋ ฅ
โ llama.cpp์์ ggml_mul_mat / ggml_norm / ggml_silu / ggml_rope ๋ฑ ๊ธฐ๋ณธ node๋ค๋ง ์กฐํฉํด์ LLM ์์ฑ
โ ํ์ต์ ์๊ณ inference-only๋ผ ๊ทธ๋ํ๋ฅผ build โ run โ destroy cycle๋ก ๋ฐ๋ณต (token๋ง๋ค ๋ฐ๋ณต)
๐จ ์์ฝ ๊ทธ๋ฆผ
[Embedding] โ [N layers (Attention + FFN)] โ [Norm + Final projection] โ [Logits] โ [Sampling โ Output token]
๋ต๊ธ ๋จ๊ธฐ๊ธฐ