質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

LLM

LLM(大規模言語モデル)は、膨大なデータセットとディープラーニング技術により構築された言語モデル。データ量・計算量・パラメータ量の3つの要素が従来の言語モデルよりも大幅に強化され、より高精度な言語処理が可能です。

Q&A

解決済

1回答

158閲覧

llama.cppにおいて、どの関数・ファイルでモデルの計算が行われているかわからない。

salmonyukke

総合スコア3

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

LLM

LLM(大規模言語モデル)は、膨大なデータセットとディープラーニング技術により構築された言語モデル。データ量・計算量・パラメータ量の3つの要素が従来の言語モデルよりも大幅に強化され、より高精度な言語処理が可能です。

0グッド

0クリップ

投稿2024/10/31 15:33

実現したいこと

llama.cppにおいてモデルの計算を行っている部分を特定したいです。

前提

以前の質問の回答で、llama.cppでモデルを読み込み、計算をし、出力に至るまでの流れは掴めました。
しかし、実際に計算が行われている部分を深堀したところ手詰まりになってしまいました。

そもそも、見るべき関数があっているのか、もしくは、直接的に見る箇所を教えていただけると嬉しいです。
このような大規模なコードを見るのが初めてなので、少しでも丁寧に助言していただけると嬉しいです。
よろしくお願いいたします。

発生している問題・エラーメッセージ

該当のソースコード

enum ggml_status ggml_backend_graph_compute_async(ggml_backend_t backend, struct ggml_cgraph * cgraph) {
return backend->iface.graph_compute(backend, cgraph);
}

試したこと

モデルの計算という事で、main.cpp内の
llama_encode関数
に目を付けました。
そこから、
llama_encode_internal関数
llama_graph_compute関数
ggml_backend_sched_graph_compute_async関数
ggml_backend_sched_compute関数
の順で追っていたのですが、上記にあるようなソースコードで息詰まってしまいました。

vscodeの機能で、graph_computeメソッドを探しても見つからない状況です。

補足情報(FW/ツールのバージョンなど)

https://github.com/ggerganov/llama.cpp

llama.cppのgitページです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

だいぶ解析進まれてますね。
タイトルに書かれている目的を達成するような回答ではありませんが、
以下の内容についての情報をお出しするため、シンタックスハイライトがされて見やすい回答欄を使わせてもらいます。

---------以下質問内容より抜粋------------------

cpp

1enum ggml_status ggml_backend_graph_compute_async(ggml_backend_t backend, struct ggml_cgraph * cgraph) { 2return backend->iface.graph_compute(backend, cgraph); 3}

上記にあるようなソースコードで息詰まってしまいました。
vscodeの機能で、graph_computeメソッドを探しても見つからない状況です。
---------以上質問内容より抜粋------------------

これはちょっと辿りづらいコードですね。
graph_computeは以下にある通り、構造体の中に定義されている関数ポインタです。
https://github.com/ggerganov/llama.cpp/blob/master/ggml/src/ggml-backend-impl.h#L107-L108

cpp

1// compute graph (always async if supported by the backend) 2enum ggml_status (*graph_compute) (ggml_backend_t backend, struct ggml_cgraph * cgraph);

このため、graph_computeというそのものの関数の定義は存在せず、backend->iface.graph_compute(backend, cgraph)ではgraph_computeに代入されている関数が呼ばれていることになります。

では、このgraph_computeはどこで設定されているかというと、ggml_backend_i構造体を保持しているggml_backend_buffer構造体の初期化で設定されています。
ggml_backendの定義はこんな感じ。

https://github.com/ggerganov/llama.cpp/blob/master/ggml/src/ggml-backend-impl.h#L117-L122

cpp

1 struct ggml_backend { 2 ggml_guid_t guid; 3 struct ggml_backend_i iface; 4 ggml_backend_dev_t device; 5 void * context; 6 };

この初期化をしている部分を探してみると色々でてくるのですが例えば以下のようなcreate_backend()で実施されていることが分かります。
https://github.com/ggerganov/llama.cpp/blob/master/examples/rpc/rpc-server.cpp#L72-L100

cpp

1static ggml_backend_t create_backend() { 2 ggml_backend_t backend = NULL; 3(各環境用のコードなので省略) 4 // if there aren't GPU Backends fallback to CPU backend 5 if (!backend) { 6 fprintf(stderr, "%s: using CPU backend\n", __func__); 7 backend = ggml_backend_cpu_init(); 8 } 9 return backend; 10}

GPUを利用するための実装はいったん置いておいて、辿りやすいCPU用のggml_backend_cpu_init()を確認してみます。

https://github.com/ggerganov/llama.cpp/blob/master/ggml/src/ggml-backend.cpp#L1034-L1060

cpp

1ggml_backend_t ggml_backend_cpu_init(void) { 2(今回の内容とは直接関係しないため省略) 3 ggml_backend_t cpu_backend = new ggml_backend { 4 /* .guid = */ ggml_backend_cpu_guid(), 5 /* .interface = */ ggml_backend_cpu_i, 6 /* .device = */ ggml_backend_reg_dev_get(ggml_backend_cpu_reg(), 0), 7 /* .context = */ ctx, 8 }; 9 10 if (cpu_backend == NULL) { 11 delete ctx; 12 return NULL; 13 } 14 15 return cpu_backend; 16}

この.interfaceに代入されているggml_backend_cpu_iが目当てのデータです。
これはすぐ上に定義されています。

https://github.com/ggerganov/llama.cpp/blob/master/ggml/src/ggml-backend.cpp#L1013-L1027

cpp

1static const struct ggml_backend_i ggml_backend_cpu_i = { 2 /* .get_name = */ ggml_backend_cpu_get_name, 3 /* .free = */ ggml_backend_cpu_free, 4 /* .set_tensor_async = */ NULL, 5 /* .get_tensor_async = */ NULL, 6 /* .cpy_tensor_async = */ NULL, 7 /* .synchronize = */ NULL, 8 /* .graph_plan_create = */ ggml_backend_cpu_graph_plan_create, 9 /* .graph_plan_free = */ ggml_backend_cpu_graph_plan_free, 10 /* .graph_plan_update = */ NULL, 11 /* .graph_plan_compute = */ ggml_backend_cpu_graph_plan_compute, 12 /* .graph_compute = */ ggml_backend_cpu_graph_compute, 13 /* .event_record = */ NULL, 14 /* .event_wait = */ NULL, 15};

ということで、CPUがバックエンドの場合には.graph_computeggml_backend_cpu_graph_computeが設定されていることが分かりました。

定義はこちらですね。
https://github.com/ggerganov/llama.cpp/blob/master/ggml/src/ggml-backend.cpp#L991-L1011

ここから先は今まで通り解析できると思いますがいかがでしょうか?

投稿2024/10/31 17:20

toge_

総合スコア226

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

salmonyukke

2024/11/02 02:34

度々ご回答ありがとうございます。 遅くなりましたが、試してみます。 本当にありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問