@fugood/llama.node 0.3.2 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. package/CMakeLists.txt +2 -0
  2. package/bin/darwin/arm64/llama-node.node +0 -0
  3. package/bin/darwin/x64/llama-node.node +0 -0
  4. package/bin/linux/arm64/llama-node.node +0 -0
  5. package/bin/linux/x64/llama-node.node +0 -0
  6. package/bin/linux-vulkan/arm64/llama-node.node +0 -0
  7. package/bin/linux-vulkan/x64/llama-node.node +0 -0
  8. package/bin/win32/arm64/llama-node.node +0 -0
  9. package/bin/win32/arm64/node.lib +0 -0
  10. package/bin/win32/x64/llama-node.node +0 -0
  11. package/bin/win32/x64/node.lib +0 -0
  12. package/bin/win32-vulkan/arm64/llama-node.node +0 -0
  13. package/bin/win32-vulkan/arm64/node.lib +0 -0
  14. package/bin/win32-vulkan/x64/llama-node.node +0 -0
  15. package/bin/win32-vulkan/x64/node.lib +0 -0
  16. package/package.json +1 -1
  17. package/src/DetokenizeWorker.cpp +1 -1
  18. package/src/EmbeddingWorker.cpp +2 -2
  19. package/src/LlamaCompletionWorker.cpp +8 -8
  20. package/src/LlamaCompletionWorker.h +2 -2
  21. package/src/LlamaContext.cpp +8 -9
  22. package/src/TokenizeWorker.cpp +1 -1
  23. package/src/common.hpp +4 -4
  24. package/src/llama.cpp/.github/workflows/build.yml +43 -9
  25. package/src/llama.cpp/.github/workflows/docker.yml +3 -0
  26. package/src/llama.cpp/CMakeLists.txt +7 -4
  27. package/src/llama.cpp/cmake/arm64-apple-clang.cmake +16 -0
  28. package/src/llama.cpp/common/CMakeLists.txt +0 -2
  29. package/src/llama.cpp/common/arg.cpp +642 -607
  30. package/src/llama.cpp/common/arg.h +22 -22
  31. package/src/llama.cpp/common/common.cpp +79 -281
  32. package/src/llama.cpp/common/common.h +130 -100
  33. package/src/llama.cpp/common/json-schema-to-grammar.cpp +1 -1
  34. package/src/llama.cpp/common/log.cpp +50 -50
  35. package/src/llama.cpp/common/log.h +18 -18
  36. package/src/llama.cpp/common/ngram-cache.cpp +36 -36
  37. package/src/llama.cpp/common/ngram-cache.h +19 -19
  38. package/src/llama.cpp/common/sampling.cpp +116 -108
  39. package/src/llama.cpp/common/sampling.h +20 -20
  40. package/src/llama.cpp/docs/build.md +37 -17
  41. package/src/llama.cpp/examples/CMakeLists.txt +1 -1
  42. package/src/llama.cpp/examples/batched/batched.cpp +14 -14
  43. package/src/llama.cpp/examples/batched-bench/batched-bench.cpp +10 -11
  44. package/src/llama.cpp/examples/convert-llama2c-to-ggml/convert-llama2c-to-ggml.cpp +1 -1
  45. package/src/llama.cpp/examples/cvector-generator/cvector-generator.cpp +9 -9
  46. package/src/llama.cpp/examples/embedding/embedding.cpp +12 -12
  47. package/src/llama.cpp/examples/eval-callback/eval-callback.cpp +8 -8
  48. package/src/llama.cpp/examples/export-lora/export-lora.cpp +5 -5
  49. package/src/llama.cpp/examples/gen-docs/gen-docs.cpp +7 -7
  50. package/src/llama.cpp/examples/gritlm/gritlm.cpp +18 -18
  51. package/src/llama.cpp/examples/imatrix/imatrix.cpp +20 -11
  52. package/src/llama.cpp/examples/infill/infill.cpp +40 -86
  53. package/src/llama.cpp/examples/llama-bench/llama-bench.cpp +42 -151
  54. package/src/llama.cpp/examples/llama.android/llama/build.gradle.kts +1 -0
  55. package/src/llama.cpp/examples/llama.android/llama/src/main/cpp/llama-android.cpp +11 -14
  56. package/src/llama.cpp/examples/llava/clip.cpp +1 -0
  57. package/src/llama.cpp/examples/llava/llava-cli.cpp +23 -23
  58. package/src/llama.cpp/examples/llava/llava.cpp +37 -3
  59. package/src/llama.cpp/examples/llava/minicpmv-cli.cpp +21 -21
  60. package/src/llama.cpp/examples/lookahead/lookahead.cpp +26 -26
  61. package/src/llama.cpp/examples/lookup/lookup-create.cpp +7 -7
  62. package/src/llama.cpp/examples/lookup/lookup-merge.cpp +4 -4
  63. package/src/llama.cpp/examples/lookup/lookup-stats.cpp +14 -14
  64. package/src/llama.cpp/examples/lookup/lookup.cpp +29 -29
  65. package/src/llama.cpp/examples/main/main.cpp +64 -109
  66. package/src/llama.cpp/examples/parallel/parallel.cpp +18 -19
  67. package/src/llama.cpp/examples/passkey/passkey.cpp +14 -14
  68. package/src/llama.cpp/examples/perplexity/perplexity.cpp +99 -120
  69. package/src/llama.cpp/examples/quantize-stats/quantize-stats.cpp +10 -9
  70. package/src/llama.cpp/examples/retrieval/retrieval.cpp +13 -13
  71. package/src/llama.cpp/examples/rpc/rpc-server.cpp +3 -1
  72. package/src/llama.cpp/examples/save-load-state/save-load-state.cpp +34 -17
  73. package/src/llama.cpp/examples/server/CMakeLists.txt +4 -13
  74. package/src/llama.cpp/examples/server/server.cpp +553 -691
  75. package/src/llama.cpp/examples/server/utils.hpp +312 -25
  76. package/src/llama.cpp/examples/simple/CMakeLists.txt +1 -1
  77. package/src/llama.cpp/examples/simple/simple.cpp +128 -96
  78. package/src/llama.cpp/examples/simple-chat/CMakeLists.txt +5 -0
  79. package/src/llama.cpp/examples/simple-chat/simple-chat.cpp +197 -0
  80. package/src/llama.cpp/examples/speculative/speculative.cpp +54 -51
  81. package/src/llama.cpp/examples/tokenize/tokenize.cpp +2 -2
  82. package/src/llama.cpp/ggml/CMakeLists.txt +15 -9
  83. package/src/llama.cpp/ggml/include/ggml-amx.h +25 -0
  84. package/src/llama.cpp/ggml/include/ggml-backend.h +46 -33
  85. package/src/llama.cpp/ggml/include/ggml-blas.h +5 -3
  86. package/src/llama.cpp/ggml/include/ggml-cann.h +9 -7
  87. package/src/llama.cpp/ggml/include/ggml-cpp.h +38 -0
  88. package/src/llama.cpp/ggml/include/ggml-cpu.h +177 -0
  89. package/src/llama.cpp/ggml/include/ggml-cuda.h +12 -12
  90. package/src/llama.cpp/ggml/include/ggml-kompute.h +7 -3
  91. package/src/llama.cpp/ggml/include/ggml-metal.h +11 -7
  92. package/src/llama.cpp/ggml/include/ggml-opt.h +216 -0
  93. package/src/llama.cpp/ggml/include/ggml-rpc.h +9 -5
  94. package/src/llama.cpp/ggml/include/ggml-sycl.h +18 -11
  95. package/src/llama.cpp/ggml/include/ggml-vulkan.h +10 -8
  96. package/src/llama.cpp/ggml/include/ggml.h +53 -393
  97. package/src/llama.cpp/ggml/src/CMakeLists.txt +66 -1149
  98. package/src/llama.cpp/ggml/src/ggml-aarch64.c +46 -3126
  99. package/src/llama.cpp/ggml/src/ggml-aarch64.h +0 -20
  100. package/src/llama.cpp/ggml/src/ggml-alloc.c +23 -27
  101. package/src/llama.cpp/ggml/src/ggml-amx/CMakeLists.txt +107 -0
  102. package/src/llama.cpp/ggml/src/ggml-amx/common.h +94 -0
  103. package/src/llama.cpp/ggml/src/ggml-amx/ggml-amx.cpp +446 -0
  104. package/src/llama.cpp/ggml/src/ggml-amx/mmq.cpp +2510 -0
  105. package/src/llama.cpp/ggml/src/ggml-amx/mmq.h +17 -0
  106. package/src/llama.cpp/ggml/src/ggml-backend-impl.h +6 -25
  107. package/src/llama.cpp/ggml/src/ggml-backend-reg.cpp +195 -0
  108. package/src/llama.cpp/ggml/src/ggml-backend.cpp +303 -864
  109. package/src/llama.cpp/ggml/src/ggml-blas/CMakeLists.txt +91 -0
  110. package/src/llama.cpp/ggml/src/{ggml-blas.cpp → ggml-blas/ggml-blas.cpp} +213 -65
  111. package/src/llama.cpp/ggml/src/ggml-cann/CMakeLists.txt +46 -0
  112. package/src/llama.cpp/ggml/src/{ggml-cann.cpp → ggml-cann/ggml-cann.cpp} +255 -149
  113. package/src/llama.cpp/ggml/src/ggml-cpu/CMakeLists.txt +261 -0
  114. package/src/llama.cpp/ggml/src/ggml-cpu/ggml-cpu-aarch64.c +3560 -0
  115. package/src/llama.cpp/ggml/src/ggml-cpu/ggml-cpu-aarch64.h +30 -0
  116. package/src/llama.cpp/ggml/src/{ggml-cpu-impl.h → ggml-cpu/ggml-cpu-impl.h} +0 -243
  117. package/src/llama.cpp/ggml/src/ggml-cpu/ggml-cpu-quants.c +10822 -0
  118. package/src/llama.cpp/ggml/src/ggml-cpu/ggml-cpu-quants.h +63 -0
  119. package/src/llama.cpp/ggml/src/ggml-cpu/ggml-cpu.c +13970 -0
  120. package/src/llama.cpp/ggml/src/ggml-cpu/ggml-cpu.cpp +663 -0
  121. package/src/llama.cpp/ggml/src/{llamafile → ggml-cpu/llamafile}/sgemm.cpp +667 -1
  122. package/src/llama.cpp/ggml/src/ggml-cuda/CMakeLists.txt +155 -0
  123. package/src/llama.cpp/ggml/src/ggml-hip/CMakeLists.txt +106 -0
  124. package/src/llama.cpp/ggml/src/ggml-impl.h +366 -16
  125. package/src/llama.cpp/ggml/src/ggml-kompute/CMakeLists.txt +162 -0
  126. package/src/llama.cpp/ggml/src/{ggml-kompute.cpp → ggml-kompute/ggml-kompute.cpp} +238 -72
  127. package/src/llama.cpp/ggml/src/ggml-metal/CMakeLists.txt +108 -0
  128. package/src/llama.cpp/ggml/src/ggml-metal/ggml-metal-impl.h +249 -0
  129. package/src/llama.cpp/ggml/src/ggml-musa/CMakeLists.txt +100 -0
  130. package/src/llama.cpp/ggml/src/ggml-opt.cpp +867 -0
  131. package/src/llama.cpp/ggml/src/ggml-quants.c +187 -10692
  132. package/src/llama.cpp/ggml/src/ggml-quants.h +78 -125
  133. package/src/llama.cpp/ggml/src/ggml-rpc/CMakeLists.txt +11 -0
  134. package/src/llama.cpp/ggml/src/{ggml-rpc.cpp → ggml-rpc/ggml-rpc.cpp} +475 -300
  135. package/src/llama.cpp/ggml/src/ggml-sycl/CMakeLists.txt +81 -0
  136. package/src/llama.cpp/ggml/src/ggml-sycl/backend.hpp +3 -0
  137. package/src/llama.cpp/ggml/src/ggml-sycl/common.cpp +40 -0
  138. package/src/llama.cpp/ggml/src/ggml-sycl/common.hpp +258 -0
  139. package/src/llama.cpp/ggml/src/ggml-sycl/concat.cpp +1 -0
  140. package/src/llama.cpp/ggml/src/ggml-sycl/dpct/helper.hpp +2 -22
  141. package/src/llama.cpp/ggml/src/ggml-sycl/element_wise.cpp +1011 -0
  142. package/src/llama.cpp/ggml/src/ggml-sycl/element_wise.hpp +76 -0
  143. package/src/llama.cpp/ggml/src/{ggml-sycl.cpp → ggml-sycl/ggml-sycl.cpp} +3584 -4142
  144. package/src/llama.cpp/ggml/src/ggml-sycl/mmvq.cpp +69 -67
  145. package/src/llama.cpp/ggml/src/ggml-sycl/norm.cpp +3 -3
  146. package/src/llama.cpp/ggml/src/ggml-sycl/outprod.cpp +56 -0
  147. package/src/llama.cpp/ggml/src/ggml-sycl/outprod.hpp +11 -0
  148. package/src/llama.cpp/ggml/src/ggml-sycl/presets.hpp +6 -0
  149. package/src/llama.cpp/ggml/src/ggml-sycl/vecdotq.hpp +4 -4
  150. package/src/llama.cpp/ggml/src/ggml-sycl/wkv6.cpp +138 -0
  151. package/src/llama.cpp/ggml/src/ggml-sycl/wkv6.hpp +10 -0
  152. package/src/llama.cpp/ggml/src/ggml-threading.cpp +12 -0
  153. package/src/llama.cpp/ggml/src/ggml-threading.h +12 -0
  154. package/src/llama.cpp/ggml/src/ggml-vulkan/CMakeLists.txt +78 -0
  155. package/src/llama.cpp/ggml/src/{ggml-vulkan.cpp → ggml-vulkan/ggml-vulkan.cpp} +555 -623
  156. package/src/llama.cpp/ggml/src/{vulkan-shaders → ggml-vulkan/vulkan-shaders}/vulkan-shaders-gen.cpp +125 -206
  157. package/src/llama.cpp/ggml/src/ggml.c +4032 -19890
  158. package/src/llama.cpp/include/llama.h +67 -33
  159. package/src/llama.cpp/pocs/vdot/q8dot.cpp +4 -3
  160. package/src/llama.cpp/pocs/vdot/vdot.cpp +8 -7
  161. package/src/llama.cpp/src/CMakeLists.txt +2 -1
  162. package/src/llama.cpp/src/llama-sampling.cpp +745 -105
  163. package/src/llama.cpp/src/llama-sampling.h +21 -2
  164. package/src/llama.cpp/src/llama-vocab.cpp +49 -9
  165. package/src/llama.cpp/src/llama-vocab.h +35 -11
  166. package/src/llama.cpp/src/llama.cpp +2636 -2406
  167. package/src/llama.cpp/src/unicode-data.cpp +2 -2
  168. package/src/llama.cpp/tests/CMakeLists.txt +1 -2
  169. package/src/llama.cpp/tests/test-arg-parser.cpp +14 -14
  170. package/src/llama.cpp/tests/test-backend-ops.cpp +185 -60
  171. package/src/llama.cpp/tests/test-barrier.cpp +1 -0
  172. package/src/llama.cpp/tests/test-chat-template.cpp +9 -5
  173. package/src/llama.cpp/tests/test-json-schema-to-grammar.cpp +17 -4
  174. package/src/llama.cpp/tests/test-log.cpp +2 -2
  175. package/src/llama.cpp/tests/test-opt.cpp +853 -142
  176. package/src/llama.cpp/tests/test-quantize-fns.cpp +22 -19
  177. package/src/llama.cpp/tests/test-quantize-perf.cpp +16 -14
  178. package/src/llama.cpp/tests/test-rope.cpp +1 -0
  179. package/src/llama.cpp/tests/test-sampling.cpp +162 -137
  180. package/src/llama.cpp/tests/test-tokenizer-0.cpp +7 -7
  181. package/src/llama.cpp/tests/test-tokenizer-1-bpe.cpp +5 -5
  182. package/src/llama.cpp/tests/test-tokenizer-1-spm.cpp +5 -5
  183. package/src/llama.cpp/common/train.cpp +0 -1515
  184. package/src/llama.cpp/common/train.h +0 -233
  185. package/src/llama.cpp/examples/baby-llama/CMakeLists.txt +0 -5
  186. package/src/llama.cpp/examples/baby-llama/baby-llama.cpp +0 -1639
  187. package/src/llama.cpp/tests/test-grad0.cpp +0 -1683
  188. /package/src/llama.cpp/ggml/{cmake → src/ggml-cpu/cmake}/FindSIMD.cmake +0 -0
  189. /package/src/llama.cpp/ggml/src/{llamafile → ggml-cpu/llamafile}/sgemm.h +0 -0
  190. /package/src/llama.cpp/ggml/src/{vulkan-shaders → ggml-vulkan/vulkan-shaders}/CMakeLists.txt +0 -0
@@ -0,0 +1,867 @@
1
+ #include "ggml-opt.h"
2
+
3
+ #include "ggml.h"
4
+ #include "ggml-alloc.h"
5
+ #include "ggml-backend.h"
6
+ #include "ggml-impl.h"
7
+
8
+ #include <algorithm>
9
+ #include <cmath>
10
+ #include <cstdint>
11
+ #include <cinttypes>
12
+ #include <map>
13
+ #include <random>
14
+ #include <vector>
15
+
16
+ struct ggml_opt_dataset {
17
+ struct ggml_context * ctx;
18
+ ggml_backend_buffer_t buf;
19
+ struct ggml_tensor * data;
20
+ struct ggml_tensor * labels;
21
+
22
+ int64_t ndata;
23
+ int64_t ndata_shard;
24
+ size_t nbs_data;
25
+ size_t nbs_labels;
26
+
27
+ std::vector<int64_t> permutation;
28
+ };
29
+
30
+ struct ggml_opt_context {
31
+ ggml_backend_sched_t backend_sched;
32
+ ggml_cgraph * allocated_graph;
33
+ ggml_cgraph * allocated_graph_copy;
34
+ struct ggml_context * ctx_static;
35
+ struct ggml_context * ctx_static_cpu;
36
+ struct ggml_context * ctx_compute;
37
+ struct ggml_context * ctx_copy;
38
+ ggml_backend_buffer_t buf_static;
39
+ ggml_backend_buffer_t buf_static_cpu;
40
+ std::mt19937 rng;
41
+
42
+ struct ggml_tensor * inputs;
43
+ struct ggml_tensor * outputs;
44
+ struct ggml_tensor * labels;
45
+
46
+ struct ggml_tensor * loss;
47
+ struct ggml_tensor * pred;
48
+ struct ggml_tensor * ncorrect;
49
+
50
+ struct ggml_cgraph * gf;
51
+ struct ggml_cgraph * gb_grad;
52
+ struct ggml_cgraph * gb_opt;
53
+
54
+ int64_t iter;
55
+ int32_t opt_period;
56
+ int32_t opt_i;
57
+ bool loss_per_datapoint;
58
+
59
+ ggml_opt_get_optimizer_params get_opt_pars;
60
+ void * get_opt_pars_ud;
61
+ struct ggml_tensor * adamw_params;
62
+ };
63
+
64
+ struct ggml_opt_result {
65
+ int64_t ndata = 0;
66
+ std::vector<float> loss;
67
+ std::vector<int32_t> pred;
68
+ int64_t ncorrect = 0;
69
+
70
+ bool loss_per_datapoint = false;
71
+ int64_t opt_period = -1;
72
+ };
73
+
74
+ // ====== Dataset ======
75
+
76
+ ggml_opt_dataset_t ggml_opt_dataset_init(int64_t ne_datapoint, int64_t ne_label, int64_t ndata, int64_t ndata_shard) {
77
+ GGML_ASSERT(ne_datapoint > 0);
78
+ GGML_ASSERT(ne_label >= 0);
79
+ GGML_ASSERT(ndata > 0);
80
+ GGML_ASSERT(ndata_shard > 0);
81
+
82
+ ggml_opt_dataset_t result = new ggml_opt_dataset;
83
+ result->ndata = ndata;
84
+ result->ndata_shard = ndata_shard;
85
+
86
+ {
87
+ struct ggml_init_params params = {
88
+ /*.mem_size =*/ 2*ggml_tensor_overhead(),
89
+ /*.mem_buffer =*/ nullptr,
90
+ /*.no_alloc =*/ true,
91
+ };
92
+ result->ctx = ggml_init(params);
93
+ }
94
+
95
+ result->data = ggml_new_tensor_2d(result->ctx, GGML_TYPE_F32, ne_datapoint, ndata);
96
+ result->nbs_data = ggml_nbytes(result->data) * ndata_shard/ndata;
97
+
98
+ if (ne_label > 0) {
99
+ result->labels = ggml_new_tensor_2d(result->ctx, GGML_TYPE_F32, ne_label, ndata);
100
+ result->nbs_labels = ggml_nbytes(result->labels) * ndata_shard/ndata;
101
+ } else {
102
+ result->labels = nullptr;
103
+ result->nbs_labels = 0;
104
+ }
105
+
106
+ result->buf = ggml_backend_alloc_ctx_tensors_from_buft(result->ctx, ggml_backend_cpu_buffer_type());
107
+
108
+ const int64_t nshards = ndata/ndata_shard;
109
+ result->permutation.resize(nshards);
110
+ for (int64_t i = 0; i < nshards; ++i) {
111
+ result->permutation[i] = i;
112
+ }
113
+ return result;
114
+ }
115
+
116
+ void ggml_opt_dataset_free(ggml_opt_dataset_t dataset) {
117
+ ggml_backend_buffer_free(dataset->buf);
118
+ ggml_free(dataset->ctx);
119
+ delete dataset;
120
+ }
121
+
122
+ struct ggml_tensor * ggml_opt_dataset_data(ggml_opt_dataset_t dataset) {
123
+ return dataset->data;
124
+ }
125
+
126
+ struct ggml_tensor * ggml_opt_dataset_labels(ggml_opt_dataset_t dataset) {
127
+ return dataset->labels;
128
+ }
129
+
130
+ void ggml_opt_dataset_shuffle(ggml_opt_context_t opt_ctx, ggml_opt_dataset_t dataset, int64_t idata) {
131
+ GGML_ASSERT(idata <= dataset->ndata);
132
+
133
+ if (idata < 0) {
134
+ std::shuffle(dataset->permutation.begin(), dataset->permutation.end(), opt_ctx->rng);
135
+ return;
136
+ }
137
+
138
+ GGML_ASSERT(idata % dataset->ndata_shard == 0);
139
+ const int64_t ishard_max = idata / dataset->ndata_shard;
140
+ std::shuffle(dataset->permutation.begin(), dataset->permutation.begin() + ishard_max, opt_ctx->rng);
141
+ }
142
+
143
+ void ggml_opt_dataset_get_batch(ggml_opt_dataset_t dataset, struct ggml_tensor * data_batch, struct ggml_tensor * labels_batch, int64_t ibatch) {
144
+ GGML_ASSERT( data_batch && ggml_is_contiguous(data_batch));
145
+ GGML_ASSERT(!labels_batch || ggml_is_contiguous(labels_batch));
146
+ GGML_ASSERT((labels_batch == nullptr) == (dataset->labels == nullptr));
147
+
148
+ const size_t nb_data_batch = ggml_nbytes(data_batch);
149
+ GGML_ASSERT(nb_data_batch % dataset->nbs_data == 0);
150
+ const int64_t shards_per_batch = nb_data_batch / dataset->nbs_data;
151
+
152
+ if (labels_batch) {
153
+ const size_t nb_labels_batch = ggml_nbytes(labels_batch);
154
+ GGML_ASSERT(nb_labels_batch == shards_per_batch*dataset->nbs_labels);
155
+ }
156
+
157
+ GGML_ASSERT((ibatch + 1)*shards_per_batch <= int64_t(dataset->permutation.size()));
158
+
159
+ for (int64_t ishard_batch = 0; ishard_batch < shards_per_batch; ++ishard_batch) {
160
+ const int64_t ishard = dataset->permutation[ibatch*shards_per_batch + ishard_batch];
161
+
162
+ const char * ptr_data = (const char *) dataset->data->data + ishard*dataset->nbs_data;
163
+ ggml_backend_tensor_set(data_batch, ptr_data, ishard_batch*dataset->nbs_data, dataset->nbs_data);
164
+
165
+ if (!labels_batch) {
166
+ continue;
167
+ }
168
+
169
+ const char * ptr_labels = (const char *) dataset->labels->data + ishard*dataset->nbs_labels;
170
+ ggml_backend_tensor_set(labels_batch, ptr_labels, ishard_batch*dataset->nbs_labels, dataset->nbs_labels);
171
+ }
172
+ }
173
+
174
+ // ====== Model / Context ======
175
+
176
+ struct ggml_opt_optimizer_params ggml_opt_get_default_optimizer_params(void * userdata) {
177
+ GGML_UNUSED(userdata);
178
+
179
+ ggml_opt_optimizer_params result;
180
+
181
+ result.adamw.alpha = 0.001f;
182
+ result.adamw.beta1 = 0.9f;
183
+ result.adamw.beta2 = 0.999f;
184
+ result.adamw.eps = 1e-8f;
185
+ result.adamw.wd = 0.0f;
186
+
187
+ return result;
188
+ }
189
+
190
+ struct ggml_opt_params ggml_opt_default_params(
191
+ ggml_backend_sched_t backend_sched,
192
+ struct ggml_context * ctx_compute,
193
+ struct ggml_tensor * inputs,
194
+ struct ggml_tensor * outputs,
195
+ enum ggml_opt_loss_type loss_type) {
196
+ return {
197
+ /*backend_sched =*/ backend_sched,
198
+ /*ctx_compute =*/ ctx_compute,
199
+ /*inputs =*/ inputs,
200
+ /*logits =*/ outputs,
201
+ /*loss_type =*/ loss_type,
202
+ /*build_type =*/ GGML_OPT_BUILD_TYPE_OPT,
203
+ /*opt_period =*/ 1,
204
+ /*get_opt_pars =*/ ggml_opt_get_default_optimizer_params,
205
+ /*get_opt_pars_ud =*/ nullptr,
206
+ };
207
+ }
208
+
209
+ static ggml_tensor * map_tensor(std::map<ggml_tensor *, ggml_tensor *> & tensor_map, ggml_context * ctx, ggml_tensor * tensor) {
210
+ if (!tensor) {
211
+ return nullptr;
212
+ }
213
+
214
+ if (tensor_map.find(tensor) != tensor_map.end()) {
215
+ return tensor_map[tensor];
216
+ }
217
+
218
+ ggml_tensor * new_tensor = ggml_dup_tensor(ctx, tensor);
219
+ tensor_map[tensor] = new_tensor;
220
+
221
+ new_tensor->op = tensor->op;
222
+ for (int i = 0; i < GGML_MAX_DIMS; i++) {
223
+ new_tensor->nb[i] = tensor->nb[i];
224
+ }
225
+ new_tensor->flags = tensor->flags;
226
+ memcpy(new_tensor->op_params, tensor->op_params, sizeof(tensor->op_params));
227
+ strcpy(new_tensor->name, tensor->name);
228
+ new_tensor->data = tensor->data;
229
+ new_tensor->buffer = tensor->buffer;
230
+ new_tensor->extra = tensor->extra;
231
+ new_tensor->view_offs = tensor->view_offs;
232
+ new_tensor->view_src = map_tensor(tensor_map, ctx, tensor->view_src);
233
+ for (int i = 0; i < GGML_MAX_SRC; i++) {
234
+ new_tensor->src[i] = map_tensor(tensor_map, ctx, tensor->src[i]);
235
+ }
236
+
237
+ return new_tensor;
238
+ }
239
+
240
+ static ggml_cgraph * dup_graph(ggml_context * ctx, ggml_cgraph * graph) {
241
+ std::map<ggml_tensor *, ggml_tensor *> tensor_map;
242
+
243
+ ggml_cgraph * new_graph = ggml_new_graph_custom(ctx, GGML_DEFAULT_GRAPH_SIZE, /*grads =*/ true);
244
+
245
+ for (int i = 0; i < graph->n_leafs; i++) {
246
+ ggml_build_forward_expand(new_graph, map_tensor(tensor_map, ctx, graph->leafs[i]));
247
+ }
248
+ for (int i = 0; i < graph->n_nodes; i++) {
249
+ ggml_build_forward_expand(new_graph, map_tensor(tensor_map, ctx, graph->nodes[i]));
250
+ }
251
+ for (int i = 0; i < graph->n_nodes; ++i) {
252
+ const size_t igrad_src = ggml_hash_find(&graph->visited_hash_set, graph->nodes[i]);
253
+ const size_t igrad_dst = ggml_hash_find(&new_graph->visited_hash_set, new_graph->nodes[i]);
254
+ graph->grads[igrad_dst] = new_graph->grads[igrad_src];
255
+ graph->grad_accs[igrad_dst] = new_graph->grad_accs[igrad_src];
256
+ }
257
+
258
+ return new_graph;
259
+ }
260
+
261
+ static void ggml_opt_alloc_graph(ggml_opt_context_t opt_ctx, ggml_cgraph * graph) {
262
+ GGML_ASSERT(graph);
263
+ if (opt_ctx->allocated_graph == graph) {
264
+ return;
265
+ }
266
+
267
+ ggml_backend_sched_reset(opt_ctx->backend_sched); // clear allocation of previous graph
268
+
269
+ {
270
+ ggml_init_params params = {
271
+ /*.mem_size =*/ ggml_tensor_overhead() * GGML_DEFAULT_GRAPH_SIZE,
272
+ /*.mem_buffer =*/ nullptr,
273
+ /*.no_alloc =*/ true,
274
+ };
275
+ ggml_free(opt_ctx->ctx_copy);
276
+ opt_ctx->ctx_copy = ggml_init(params);
277
+ }
278
+
279
+ opt_ctx->allocated_graph_copy = dup_graph(opt_ctx->ctx_copy, graph);
280
+
281
+ ggml_backend_sched_alloc_graph(opt_ctx->backend_sched, opt_ctx->allocated_graph_copy);
282
+ opt_ctx->allocated_graph = graph;
283
+ }
284
+
285
+ ggml_opt_context_t ggml_opt_init(struct ggml_opt_params params) {
286
+ ggml_opt_context_t result = new struct ggml_opt_context;
287
+ result->backend_sched = params.backend_sched;
288
+ result->allocated_graph = nullptr;
289
+ result->allocated_graph_copy = nullptr;
290
+ result->ctx_compute = params.ctx_compute;
291
+ result->ctx_copy = nullptr;
292
+ result->inputs = params.inputs;
293
+ result->outputs = params.outputs;
294
+ result->iter = 1;
295
+ result->opt_period = params.opt_period;
296
+ result->opt_i = 0;
297
+ result->get_opt_pars = params.get_opt_pars;
298
+ result->get_opt_pars_ud = params.get_opt_pars_ud;
299
+
300
+ GGML_ASSERT(result->inputs->data && "the inputs must be allocated statically");
301
+ GGML_ASSERT(result->opt_period >= 1);
302
+
303
+ const bool accumulate = params.build_type == GGML_OPT_BUILD_TYPE_GRAD ||
304
+ (params.build_type == GGML_OPT_BUILD_TYPE_OPT && result->opt_period > 1);
305
+
306
+ ggml_set_input(result->inputs);
307
+ ggml_set_output(result->outputs);
308
+
309
+ result->gf = ggml_new_graph_custom(result->ctx_compute, GGML_DEFAULT_GRAPH_SIZE, /*grads =*/ true); // Forward pass.
310
+ ggml_build_forward_expand(result->gf, result->outputs);
311
+
312
+ int n_param = 0;
313
+ for (int i = 0; i < result->gf->n_nodes; ++i) {
314
+ if (result->gf->nodes[i]->flags & GGML_TENSOR_FLAG_PARAM) {
315
+ n_param++;
316
+ }
317
+ }
318
+
319
+ {
320
+ // The static context is used for:
321
+ // - gradients (1 tensor per param if using gradient accumulation)
322
+ // - optimizer momenta (2 tensors per param)
323
+ // - labels
324
+ // - loss + its gradient (up to 5 tensors)
325
+ // - pred
326
+ // - ncorrect (2 tensors).
327
+ const size_t tensors_per_param = (accumulate ? 1 : 0) + (params.build_type == GGML_OPT_BUILD_TYPE_OPT ? 2 : 0);
328
+ const size_t size_meta = (tensors_per_param*n_param + 9) * ggml_tensor_overhead();
329
+ struct ggml_init_params params = {
330
+ /*.mem_size =*/ size_meta,
331
+ /*.mem_buffer =*/ nullptr,
332
+ /*.no_alloc =*/ true,
333
+ };
334
+ result->ctx_static = ggml_init(params);
335
+ }
336
+ {
337
+ // The static cpu context is used for:
338
+ // - optimizer parameters (1 for the entire context)
339
+ const size_t size_meta = 1 * ggml_tensor_overhead();
340
+ struct ggml_init_params params = {
341
+ /*.mem_size =*/ size_meta,
342
+ /*.mem_buffer =*/ nullptr,
343
+ /*.no_alloc =*/ true,
344
+ };
345
+ result->ctx_static_cpu = ggml_init(params);
346
+ }
347
+
348
+
349
+ switch (params.loss_type) {
350
+ case GGML_OPT_LOSS_TYPE_MEAN: {
351
+ result->labels = nullptr;
352
+ result->loss = ggml_sum(result->ctx_static, result->outputs);
353
+ ggml_set_name(result->loss, "loss_sum");
354
+ const float scale = 1.0f / (result->opt_period * ggml_nelements(result->outputs));
355
+ result->loss = ggml_scale(result->ctx_static, result->loss, scale);
356
+ ggml_set_name(result->loss, "loss_mean");
357
+ result->loss_per_datapoint = true;
358
+ break;
359
+ }
360
+ case GGML_OPT_LOSS_TYPE_SUM: {
361
+ result->labels = nullptr;
362
+ result->loss = ggml_sum(result->ctx_static, result->outputs);
363
+ ggml_set_name(result->loss, "loss_sum");
364
+ result->loss_per_datapoint = false;
365
+ break;
366
+ }
367
+ case GGML_OPT_LOSS_TYPE_CROSS_ENTROPY: {
368
+ result->labels = ggml_dup_tensor(result->ctx_static, result->outputs);
369
+ ggml_set_input(result->labels);
370
+ ggml_set_name(result->labels, "labels");
371
+ result->loss = ggml_cross_entropy_loss(result->ctx_static, result->outputs, result->labels);
372
+ ggml_set_name(result->loss, "loss_cross_entropy");
373
+ if (result->opt_period > 1) {
374
+ result->loss = ggml_scale(result->ctx_static, result->loss, 1.0f / result->opt_period);
375
+ ggml_set_name(result->loss, "loss_cross_entropy_scaled");
376
+ }
377
+ result->loss_per_datapoint = true;
378
+ break;
379
+ }
380
+ case GGML_OPT_LOSS_TYPE_MEAN_SQUARED_ERROR: {
381
+ result->labels = ggml_dup_tensor(result->ctx_static, result->outputs);
382
+ ggml_set_input(result->labels);
383
+ ggml_set_name(result->labels, "labels");
384
+ result->loss = ggml_sub(result->ctx_static, result->outputs, result->labels);
385
+ ggml_set_name(result->loss, "loss_error");
386
+ result->loss = ggml_sqr(result->ctx_static, result->loss);
387
+ ggml_set_name(result->loss, "loss_squared_error");
388
+ result->loss = ggml_sum(result->ctx_static, result->loss);
389
+ ggml_set_name(result->loss, "loss_sum_squared_error");
390
+ const float scale = 1.0f / (result->opt_period * ggml_nelements(result->outputs));
391
+ result->loss = ggml_scale(result->ctx_static, result->loss, scale);
392
+ ggml_set_name(result->loss, "loss_mean_squared_error");
393
+ result->loss_per_datapoint = true;
394
+ break;
395
+ }
396
+ }
397
+ ggml_set_output(result->loss);
398
+ ggml_set_loss(result->loss);
399
+ ggml_build_forward_expand(result->gf, result->loss);
400
+
401
+ result->pred = ggml_argmax(result->ctx_static, result->outputs);
402
+ ggml_set_name(result->pred, "pred");
403
+ ggml_set_output(result->pred);
404
+ ggml_build_forward_expand(result->gf, result->pred);
405
+
406
+ if (result->labels) {
407
+ result->ncorrect = ggml_count_equal(result->ctx_static, result->pred, ggml_argmax(result->ctx_static, result->labels));
408
+ ggml_set_name(result->ncorrect, "ncorrect");
409
+ ggml_set_output(result->ncorrect);
410
+ ggml_build_forward_expand(result->gf, result->ncorrect);
411
+ } else {
412
+ result->ncorrect = nullptr;
413
+ }
414
+
415
+ if (params.build_type == GGML_OPT_BUILD_TYPE_FORWARD) {
416
+ result->gb_grad = nullptr;
417
+ result->gb_opt = nullptr;
418
+
419
+ result->buf_static = ggml_backend_alloc_ctx_tensors(result->ctx_static, ggml_backend_sched_get_backend(result->backend_sched, 0));
420
+ result->buf_static_cpu = nullptr;
421
+
422
+ ggml_opt_alloc_graph(result, result->gf);
423
+
424
+ return result;
425
+ }
426
+
427
+ // gb_grad == graph backward gradients, forward pass, then backward pass to calculate gradients.
428
+ result->gb_grad = ggml_graph_dup(result->ctx_compute, result->gf);
429
+ ggml_build_backward_expand(result->ctx_static, result->ctx_compute, result->gb_grad, accumulate);
430
+
431
+ if (params.build_type == GGML_OPT_BUILD_TYPE_GRAD) {
432
+ result->gb_opt = nullptr;
433
+
434
+ result->buf_static = ggml_backend_alloc_ctx_tensors(result->ctx_static, ggml_backend_sched_get_backend(result->backend_sched, 0));
435
+ result->buf_static_cpu = nullptr;
436
+
437
+ ggml_opt_alloc_graph(result, result->gb_grad);
438
+ ggml_graph_reset(result->gb_grad);
439
+
440
+ return result;
441
+ }
442
+
443
+ GGML_ASSERT(params.build_type == GGML_OPT_BUILD_TYPE_OPT);
444
+
445
+ // gb_opt == graph backward optimize, forward pass, then backward pass to calculate gradients, then optimizer step.
446
+ result->gb_opt = ggml_graph_dup(result->ctx_compute, result->gb_grad);
447
+
448
+ result->adamw_params = ggml_new_tensor_1d(result->ctx_static_cpu, GGML_TYPE_F32, 7);
449
+ ggml_set_input(result->adamw_params);
450
+ ggml_set_name(result->adamw_params, "adamw_params");
451
+
452
+ for (int i = result->gf->n_nodes-1; i >= 0; --i) {
453
+ struct ggml_tensor * node = result->gb_opt->nodes[i];
454
+ struct ggml_tensor * grad = ggml_graph_get_grad(result->gb_opt, node);
455
+
456
+ if (node->flags & GGML_TENSOR_FLAG_PARAM) {
457
+ struct ggml_tensor * m = ggml_dup_tensor(result->ctx_static, node);
458
+ struct ggml_tensor * v = ggml_dup_tensor(result->ctx_static, node);
459
+ struct ggml_tensor * opt_step = ggml_opt_step_adamw(result->ctx_compute, node, grad, m, v, result->adamw_params);
460
+ ggml_build_forward_expand(result->gb_opt, opt_step);
461
+ }
462
+ }
463
+
464
+ result->buf_static = ggml_backend_alloc_ctx_tensors(
465
+ result->ctx_static, ggml_backend_sched_get_backend(result->backend_sched, 0));
466
+
467
+ result->buf_static_cpu = ggml_backend_alloc_ctx_tensors_from_buft(result->ctx_static_cpu, ggml_backend_cpu_buffer_type());
468
+
469
+ ggml_opt_alloc_graph(result, result->gb_opt);
470
+ ggml_graph_reset(result->gb_opt);
471
+
472
+ return result;
473
+ }
474
+
475
+ void ggml_opt_free(ggml_opt_context_t opt_ctx) {
476
+ if (opt_ctx == nullptr) {
477
+ return;
478
+ }
479
+ ggml_backend_buffer_free(opt_ctx->buf_static);
480
+ ggml_backend_buffer_free(opt_ctx->buf_static_cpu);
481
+ ggml_free(opt_ctx->ctx_static);
482
+ ggml_free(opt_ctx->ctx_static_cpu);
483
+ delete opt_ctx;
484
+ }
485
+
486
+ void ggml_opt_reset(ggml_opt_context_t opt_ctx, bool optimizer) {
487
+ if (optimizer) {
488
+ ggml_graph_reset(opt_ctx->gb_opt);
489
+ opt_ctx->iter = 1;
490
+ } else {
491
+ ggml_graph_reset(opt_ctx->gb_grad);
492
+ }
493
+ }
494
+
495
+ struct ggml_tensor * ggml_opt_inputs(ggml_opt_context_t opt_ctx) {
496
+ return opt_ctx->inputs;
497
+ }
498
+
499
+ struct ggml_tensor * ggml_opt_outputs(ggml_opt_context_t opt_ctx) {
500
+ return opt_ctx->outputs;
501
+ }
502
+
503
+ struct ggml_tensor * ggml_opt_labels(ggml_opt_context_t opt_ctx) {
504
+ return opt_ctx->labels;
505
+ }
506
+
507
+ struct ggml_tensor * ggml_opt_loss(ggml_opt_context_t opt_ctx) {
508
+ return opt_ctx->loss;
509
+ }
510
+
511
+ struct ggml_tensor * ggml_opt_pred(ggml_opt_context_t opt_ctx) {
512
+ return opt_ctx->pred;
513
+ }
514
+
515
+ struct ggml_tensor * ggml_opt_ncorrect(ggml_opt_context_t opt_ctx) {
516
+ return opt_ctx->ncorrect;
517
+ }
518
+
519
+ struct ggml_tensor * ggml_opt_grad_acc(ggml_opt_context_t opt_ctx, struct ggml_tensor * node) {
520
+ return ggml_graph_get_grad_acc(opt_ctx->gb_opt, node);
521
+ }
522
+
523
+ // ====== Optimization Result ======
524
+
525
+ ggml_opt_result_t ggml_opt_result_init() {
526
+ return new ggml_opt_result;
527
+ }
528
+
529
+ void ggml_opt_result_free(ggml_opt_result_t result) {
530
+ delete result;
531
+ }
532
+
533
+ void ggml_opt_result_reset(ggml_opt_result_t result) {
534
+ result->ndata = 0;
535
+ result->loss.clear();
536
+ result->pred.clear();
537
+ result->ncorrect = 0;
538
+ }
539
+
540
+ void ggml_opt_result_ndata(ggml_opt_result_t result, int64_t * ndata) {
541
+ *ndata = result->ndata;
542
+ }
543
+
544
+ void ggml_opt_result_loss(ggml_opt_result_t result, double * loss, double * unc) {
545
+ const int64_t nbatches = result->loss.size(); // Number of physical batches.
546
+
547
+ if (nbatches == 0) {
548
+ *loss = 0.0;
549
+ *unc = NAN;
550
+ return;
551
+ }
552
+
553
+ double sum = 0.0;
554
+ double sum_squared = 0.0;
555
+
556
+ for (const float & loss : result->loss) {
557
+ // If the loss is per datapoint it was scaled by 1.0f/opt_period for each physical batch.
558
+ const float loss_scaled = result->loss_per_datapoint ? loss*result->opt_period : loss;
559
+ sum += loss_scaled;
560
+ sum_squared += loss_scaled*loss_scaled;
561
+ }
562
+
563
+ const double mean = sum/nbatches;
564
+ *loss = result->loss_per_datapoint ? mean : sum;
565
+
566
+ if (!unc) {
567
+ return;
568
+ }
569
+
570
+ if (nbatches < 2) {
571
+ *unc = NAN;
572
+ return;
573
+ }
574
+
575
+ const double var_sum = sum_squared/nbatches - mean*mean; // variance without Bessel's correction, i.e. nbatches/(nbatches-1)
576
+ *unc = result->loss_per_datapoint ? sqrt(var_sum / (nbatches - 1)) : sqrt(var_sum * nbatches/(nbatches - 1));
577
+ }
578
+
579
+ void ggml_opt_result_pred(ggml_opt_result_t result, int32_t * pred) {
580
+ for (size_t i = 0; i < result->pred.size(); ++i) {
581
+ pred[i] = result->pred[i];
582
+ }
583
+ }
584
+
585
+ void ggml_opt_result_accuracy(ggml_opt_result_t result, double * accuracy, double * unc) {
586
+ *accuracy = result->ncorrect >= 0 ? double(result->ncorrect) / double(result->ndata) : NAN;
587
+
588
+ if (!unc) {
589
+ return;
590
+ }
591
+
592
+ *unc = result->ncorrect >= 0 && result->ndata >= 2 ?
593
+ sqrt((*accuracy) * (1.0 - (*accuracy)) / double(result->ndata - 1)) : NAN;
594
+ }
595
+
596
+ // ====== Computation ======
597
+
598
+ static void ggml_opt_eval_graph(ggml_opt_context_t opt_ctx, ggml_cgraph * graph, ggml_opt_result * result) {
599
+ if (graph != opt_ctx->gf) {
600
+ struct ggml_opt_optimizer_params opt_pars = opt_ctx->get_opt_pars(opt_ctx->get_opt_pars_ud);
601
+
602
+ GGML_ASSERT(opt_pars.adamw.alpha > 0.0f);
603
+ GGML_ASSERT(opt_pars.adamw.beta1 >= 0.0f);
604
+ GGML_ASSERT(opt_pars.adamw.beta1 <= 1.0f);
605
+ GGML_ASSERT(opt_pars.adamw.beta2 >= 0.0f);
606
+ GGML_ASSERT(opt_pars.adamw.beta2 <= 1.0f);
607
+ GGML_ASSERT(opt_pars.adamw.eps >= 0.0f);
608
+ GGML_ASSERT(opt_pars.adamw.wd >= 0.0f);
609
+ GGML_ASSERT(opt_pars.adamw.wd <= 1.0f);
610
+
611
+ // beta1, beta2 after applying warmup
612
+ const float beta1h = 1.0f/(1.0f - powf(opt_pars.adamw.beta1, opt_ctx->iter));
613
+ const float beta2h = 1.0f/(1.0f - powf(opt_pars.adamw.beta2, opt_ctx->iter));
614
+
615
+ float * adamw_par_data = ggml_get_data_f32(opt_ctx->adamw_params);
616
+ adamw_par_data[0] = opt_pars.adamw.alpha;
617
+ adamw_par_data[1] = opt_pars.adamw.beta1;
618
+ adamw_par_data[2] = opt_pars.adamw.beta2;
619
+ adamw_par_data[3] = opt_pars.adamw.eps;
620
+ adamw_par_data[4] = opt_pars.adamw.wd;
621
+ adamw_par_data[5] = beta1h;
622
+ adamw_par_data[6] = beta2h;
623
+ }
624
+
625
+ ggml_opt_alloc_graph(opt_ctx, graph);
626
+ ggml_backend_sched_graph_compute(opt_ctx->backend_sched, opt_ctx->allocated_graph_copy);
627
+ opt_ctx->iter += opt_ctx->allocated_graph == opt_ctx->gb_opt;
628
+
629
+ if (!result) {
630
+ return;
631
+ }
632
+
633
+ if (result->ndata == 0) {
634
+ result->loss_per_datapoint = opt_ctx->loss_per_datapoint;
635
+ result->opt_period = opt_ctx->opt_period;
636
+ } else {
637
+ GGML_ASSERT(result->loss_per_datapoint == opt_ctx->loss_per_datapoint);
638
+ GGML_ASSERT(result->opt_period == opt_ctx->opt_period);
639
+ }
640
+
641
+ const int64_t ndata = opt_ctx->outputs->ne[1];
642
+ GGML_ASSERT(result->ndata == ndata*int64_t(result->loss.size()) && "varying batch size not supported");
643
+ result->ndata += ndata;
644
+
645
+ GGML_ASSERT(ggml_is_scalar(opt_ctx->loss));
646
+ GGML_ASSERT(opt_ctx->loss->type == GGML_TYPE_F32);
647
+ float loss;
648
+ ggml_backend_tensor_get(opt_ctx->loss, &loss, 0, ggml_nbytes(opt_ctx->loss));
649
+ result->loss.push_back(loss);
650
+
651
+ GGML_ASSERT(opt_ctx->pred->type == GGML_TYPE_I32);
652
+ std::vector<int32_t> pred(ndata);
653
+ ggml_backend_tensor_get(opt_ctx->pred, pred.data(), 0, ggml_nbytes(opt_ctx->pred));
654
+ result->pred.insert(result->pred.end(), pred.begin(), pred.end());
655
+
656
+ if (!opt_ctx->labels || result->ncorrect < 0) {
657
+ result->ncorrect = -1;
658
+ return;
659
+ }
660
+
661
+ GGML_ASSERT(ggml_is_scalar(opt_ctx->ncorrect));
662
+ GGML_ASSERT(opt_ctx->ncorrect->type == GGML_TYPE_I64);
663
+ int64_t ncorrect;
664
+ ggml_backend_tensor_get(opt_ctx->ncorrect, &ncorrect, 0, ggml_nbytes(opt_ctx->ncorrect));
665
+ result->ncorrect += ncorrect;
666
+ }
667
+
668
+ void ggml_opt_forward(ggml_opt_context_t opt_ctx, ggml_opt_result * result) {
669
+ ggml_opt_eval_graph(opt_ctx, opt_ctx->gf, result);
670
+ }
671
+
672
+ void ggml_opt_forward_backward(ggml_opt_context_t opt_ctx, ggml_opt_result * result) {
673
+ if (opt_ctx->opt_period == 1) {
674
+ ggml_opt_eval_graph(opt_ctx, opt_ctx->gb_opt, result);
675
+ return;
676
+ }
677
+
678
+ const int32_t opt_i_next = (opt_ctx->opt_i + 1) % opt_ctx->opt_period;
679
+ if (opt_i_next == 0) {
680
+ ggml_opt_eval_graph(opt_ctx, opt_ctx->gb_opt, result);
681
+ ggml_opt_reset(opt_ctx, /*optimizer =*/ false);
682
+ } else {
683
+ ggml_opt_eval_graph(opt_ctx, opt_ctx->gb_grad, result);
684
+ }
685
+ opt_ctx->opt_i = opt_i_next;
686
+ }
687
+
688
+ // ====== High-Level Functions ======
689
+
690
+ void ggml_opt_epoch(
691
+ ggml_opt_context_t opt_ctx,
692
+ ggml_opt_dataset_t dataset,
693
+ ggml_opt_result_t result_train,
694
+ ggml_opt_result_t result_eval,
695
+ int64_t idata_split,
696
+ ggml_opt_epoch_callback callback_train,
697
+ ggml_opt_epoch_callback callback_eval) {
698
+ struct ggml_tensor * inputs = ggml_opt_inputs(opt_ctx);
699
+ struct ggml_tensor * labels = ggml_opt_labels(opt_ctx);
700
+ struct ggml_tensor * data = ggml_opt_dataset_data(dataset);
701
+ GGML_ASSERT(data->ne[0] == inputs->ne[0]);
702
+
703
+ const int64_t ndata = data->ne[1];
704
+ const int64_t ndata_batch = inputs->ne[1];
705
+
706
+ GGML_ASSERT(data->ne[1] % inputs->ne[1] == 0);
707
+ const int64_t nbatches = ndata/ndata_batch;
708
+
709
+ idata_split = idata_split < 0 ? ndata : idata_split;
710
+ GGML_ASSERT(idata_split % ndata_batch == 0);
711
+ const int64_t ibatch_split = idata_split / ndata_batch;
712
+
713
+ int64_t ibatch = 0;
714
+ int64_t t_loop_start = ggml_time_us();
715
+ for (; ibatch < ibatch_split; ++ibatch) {
716
+ ggml_opt_dataset_get_batch(dataset, inputs, labels, ibatch);
717
+ ggml_opt_forward_backward(opt_ctx, result_train);
718
+ if (callback_train) {
719
+ callback_train(true, opt_ctx, dataset, result_train, ibatch+1, ibatch_split, t_loop_start);
720
+ }
721
+ }
722
+ t_loop_start = ggml_time_us();
723
+ for (; ibatch < nbatches; ++ibatch) {
724
+ ggml_opt_dataset_get_batch(dataset, inputs, labels, ibatch);
725
+ ggml_opt_forward(opt_ctx, result_eval);
726
+ if (callback_eval) {
727
+ callback_eval(false, opt_ctx, dataset, result_eval, ibatch+1-ibatch_split, nbatches-ibatch_split, t_loop_start);
728
+ }
729
+ }
730
+ }
731
+
732
+ void ggml_opt_epoch_callback_progress_bar(
733
+ bool train,
734
+ ggml_opt_context_t opt_ctx,
735
+ ggml_opt_dataset_t dataset,
736
+ ggml_opt_result_t result,
737
+ int64_t ibatch,
738
+ int64_t ibatch_max,
739
+ int64_t t_start_us) {
740
+ fprintf(stderr, "%s[", train ? "train: " : "val: ");
741
+
742
+ constexpr int64_t bar_length = 25;
743
+ for (int64_t j = 0; j < bar_length; ++j) {
744
+ const int64_t ibatch_j = ibatch_max * j/bar_length;
745
+ if (ibatch_j < ibatch) {
746
+ fprintf(stderr, "=");
747
+ } else if (ibatch_max * (j - 1)/bar_length < ibatch) {
748
+ fprintf(stderr, ">");
749
+ } else {
750
+ fprintf(stderr, " ");
751
+ }
752
+ }
753
+
754
+ const int64_t batch_size = ggml_opt_inputs(opt_ctx)->ne[1];
755
+ const int64_t idata = ibatch*batch_size;
756
+ const int64_t idata_max = ibatch_max*batch_size;
757
+
758
+ double loss;
759
+ double loss_unc;
760
+ ggml_opt_result_loss(result, &loss, &loss_unc);
761
+
762
+ double accuracy;
763
+ double accuracy_unc;
764
+ ggml_opt_result_accuracy(result, &accuracy, &accuracy_unc);
765
+
766
+ const int64_t t_ibatch_us = ggml_time_us() - t_start_us;
767
+ int64_t t_ibatch_s = t_ibatch_us / 1000000;
768
+ const int64_t t_ibatch_h = t_ibatch_s / 3600;
769
+ t_ibatch_s -= t_ibatch_h * 3600;
770
+ const int64_t t_ibatch_m = t_ibatch_s / 60;
771
+ t_ibatch_s -= t_ibatch_m * 60;
772
+
773
+ const int64_t t_eta_us = t_ibatch_us * (ibatch_max - ibatch)/ibatch;
774
+ int64_t t_eta_s = t_eta_us / 1000000;
775
+ const int64_t t_eta_h = t_eta_s / 3600;
776
+ t_eta_s -= t_eta_h * 3600;
777
+ const int64_t t_eta_m = t_eta_s / 60;
778
+ t_eta_s -= t_eta_m * 60;
779
+
780
+ fprintf(stderr, "| data=%06" PRId64 "/%06" PRId64 ", loss=%.6lf+-%.6lf, accuracy=%.2lf+-%.2lf%%, "
781
+ "t=%02" PRId64 ":%02" PRId64 ":%02" PRId64 ", ETA=%02" PRId64 ":%02" PRId64 ":%02" PRId64 "]\r",
782
+ idata, idata_max, loss, loss_unc, 100.0*accuracy, 100.0*accuracy_unc,
783
+ t_ibatch_h, t_ibatch_m, t_ibatch_s, t_eta_h, t_eta_m, t_eta_s);
784
+ if (ibatch == ibatch_max) {
785
+ fprintf(stderr, "\n");
786
+ }
787
+ fflush(stderr);
788
+
789
+ GGML_UNUSED(dataset);
790
+ }
791
+
792
+ void ggml_opt_fit(
793
+ ggml_backend_sched_t backend_sched,
794
+ ggml_context * ctx_compute,
795
+ ggml_tensor * inputs,
796
+ ggml_tensor * outputs,
797
+ ggml_opt_dataset_t dataset,
798
+ enum ggml_opt_loss_type loss_type,
799
+ ggml_opt_get_optimizer_params get_opt_pars,
800
+ int64_t nepoch,
801
+ int64_t nbatch_logical,
802
+ float val_split,
803
+ bool silent) {
804
+ ggml_time_init();
805
+ const int64_t t_start_us = ggml_time_us();
806
+
807
+ const int64_t ndata = ggml_opt_dataset_data(dataset)->ne[1];
808
+ const int64_t nbatch_physical = inputs->ne[1];
809
+ GGML_ASSERT(ndata % nbatch_logical == 0);
810
+ GGML_ASSERT(nbatch_logical % nbatch_physical == 0);
811
+
812
+ const int64_t opt_period = nbatch_logical / nbatch_physical;
813
+ const int64_t nbatches_logical = ndata / nbatch_logical;
814
+
815
+ GGML_ASSERT(val_split >= 0.0f);
816
+ GGML_ASSERT(val_split < 1.0f);
817
+ const int64_t ibatch_split = int64_t(((1.0f - val_split) * nbatches_logical)) * opt_period; // train <-> val split index (physical)
818
+ const int64_t idata_split = ibatch_split * nbatch_physical;
819
+
820
+ int64_t epoch = 1;
821
+
822
+ ggml_opt_params params = ggml_opt_default_params(backend_sched, ctx_compute, inputs, outputs, loss_type);
823
+ params.opt_period = opt_period;
824
+ params.get_opt_pars = get_opt_pars;
825
+ params.get_opt_pars_ud = &epoch;
826
+ ggml_opt_context_t opt_ctx = ggml_opt_init(params);
827
+
828
+ // Shuffling the data is generally useful but there is only a point if not all data is used in a single batch.
829
+ if (nbatch_logical < ndata) {
830
+ ggml_opt_dataset_shuffle(opt_ctx, dataset, -1); // Shuffle all data (train + validation).
831
+ }
832
+
833
+ ggml_opt_result_t result_train = ggml_opt_result_init();
834
+ ggml_opt_result_t result_val = ggml_opt_result_init();
835
+
836
+ ggml_opt_epoch_callback epoch_callback = silent ? nullptr : ggml_opt_epoch_callback_progress_bar;
837
+
838
+ for (; epoch <= nepoch; ++epoch) {
839
+ if (nbatch_logical < idata_split) {
840
+ ggml_opt_dataset_shuffle(opt_ctx, dataset, idata_split);
841
+ }
842
+
843
+ ggml_opt_result_reset(result_train);
844
+ ggml_opt_result_reset(result_val);
845
+
846
+ if (!silent) {
847
+ fprintf(stderr, "%s: epoch %04" PRId64 "/%04" PRId64 ":\n", __func__, epoch, nepoch);
848
+ }
849
+ ggml_opt_epoch(opt_ctx, dataset, result_train, result_val, idata_split, epoch_callback, epoch_callback);
850
+ if (!silent) {
851
+ fprintf(stderr, "\n");
852
+ }
853
+ }
854
+
855
+ if (!silent) {
856
+ int64_t t_total_s = (ggml_time_us() - t_start_us) / 1000000;
857
+ const int64_t t_total_h = t_total_s / 3600;
858
+ t_total_s -= t_total_h * 3600;
859
+ const int64_t t_total_m = t_total_s / 60;
860
+ t_total_s -= t_total_m * 60;
861
+ fprintf(stderr, "%s: training took %02" PRId64 ":%02" PRId64 ":%02" PRId64 "\n", __func__, t_total_h, t_total_m, t_total_s);
862
+ }
863
+
864
+ ggml_opt_free(opt_ctx);
865
+ ggml_opt_result_free(result_train);
866
+ ggml_opt_result_free(result_val);
867
+ }