whispercpp 1.3.0 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (132) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +5 -0
  3. data/LICENSE +1 -1
  4. data/README.md +165 -434
  5. data/Rakefile +60 -11
  6. data/ext/.gitignore +13 -0
  7. data/ext/cpu.mk +9 -0
  8. data/ext/{dr_wav.h → examples/dr_wav.h} +3560 -1179
  9. data/ext/extconf.rb +185 -16
  10. data/ext/ggml/include/ggml-alloc.h +76 -0
  11. data/ext/ggml/include/ggml-backend.h +352 -0
  12. data/ext/ggml/include/ggml-blas.h +25 -0
  13. data/ext/ggml/include/ggml-cann.h +123 -0
  14. data/ext/ggml/include/ggml-cpp.h +38 -0
  15. data/ext/ggml/include/ggml-cpu.h +135 -0
  16. data/ext/ggml/include/ggml-cuda.h +47 -0
  17. data/ext/ggml/include/ggml-kompute.h +50 -0
  18. data/ext/ggml/include/ggml-metal.h +66 -0
  19. data/ext/ggml/include/ggml-opencl.h +26 -0
  20. data/ext/ggml/include/ggml-opt.h +216 -0
  21. data/ext/ggml/include/ggml-rpc.h +28 -0
  22. data/ext/ggml/include/ggml-sycl.h +49 -0
  23. data/ext/ggml/include/ggml-vulkan.h +31 -0
  24. data/ext/{ggml.h → ggml/include/ggml.h} +479 -596
  25. data/ext/ggml/src/ggml-alloc.c +1037 -0
  26. data/ext/ggml/src/ggml-amx/common.h +94 -0
  27. data/ext/ggml/src/ggml-amx/ggml-amx.cpp +446 -0
  28. data/ext/ggml/src/ggml-amx/mmq.cpp +2510 -0
  29. data/ext/ggml/src/ggml-amx/mmq.h +17 -0
  30. data/ext/ggml/src/ggml-backend-impl.h +256 -0
  31. data/ext/ggml/src/ggml-backend-reg.cpp +552 -0
  32. data/ext/ggml/src/ggml-backend.cpp +1999 -0
  33. data/ext/ggml/src/ggml-blas/ggml-blas.cpp +517 -0
  34. data/ext/ggml/src/ggml-cann/acl_tensor.cpp +175 -0
  35. data/ext/ggml/src/ggml-cann/acl_tensor.h +258 -0
  36. data/ext/ggml/src/ggml-cann/aclnn_ops.cpp +3427 -0
  37. data/ext/ggml/src/ggml-cann/aclnn_ops.h +592 -0
  38. data/ext/ggml/src/ggml-cann/common.h +286 -0
  39. data/ext/ggml/src/ggml-cann/ggml-cann.cpp +2188 -0
  40. data/ext/ggml/src/ggml-cann/kernels/ascendc_kernels.h +19 -0
  41. data/ext/ggml/src/ggml-cann/kernels/dup.cpp +236 -0
  42. data/ext/ggml/src/ggml-cann/kernels/get_row_f16.cpp +197 -0
  43. data/ext/ggml/src/ggml-cann/kernels/get_row_f32.cpp +190 -0
  44. data/ext/ggml/src/ggml-cann/kernels/get_row_q4_0.cpp +204 -0
  45. data/ext/ggml/src/ggml-cann/kernels/get_row_q8_0.cpp +191 -0
  46. data/ext/ggml/src/ggml-cann/kernels/quantize_f16_q8_0.cpp +218 -0
  47. data/ext/ggml/src/ggml-cann/kernels/quantize_f32_q8_0.cpp +216 -0
  48. data/ext/ggml/src/ggml-cann/kernels/quantize_float_to_q4_0.cpp +295 -0
  49. data/ext/ggml/src/ggml-common.h +1853 -0
  50. data/ext/ggml/src/ggml-cpu/amx/amx.cpp +220 -0
  51. data/ext/ggml/src/ggml-cpu/amx/amx.h +8 -0
  52. data/ext/ggml/src/ggml-cpu/amx/common.h +91 -0
  53. data/ext/ggml/src/ggml-cpu/amx/mmq.cpp +2511 -0
  54. data/ext/ggml/src/ggml-cpu/amx/mmq.h +10 -0
  55. data/ext/ggml/src/ggml-cpu/cpu-feats-x86.cpp +323 -0
  56. data/ext/ggml/src/ggml-cpu/ggml-cpu-aarch64.cpp +4262 -0
  57. data/ext/ggml/src/ggml-cpu/ggml-cpu-aarch64.h +8 -0
  58. data/ext/ggml/src/ggml-cpu/ggml-cpu-hbm.cpp +55 -0
  59. data/ext/ggml/src/ggml-cpu/ggml-cpu-hbm.h +8 -0
  60. data/ext/ggml/src/ggml-cpu/ggml-cpu-impl.h +386 -0
  61. data/ext/ggml/src/ggml-cpu/ggml-cpu-quants.c +10835 -0
  62. data/ext/ggml/src/ggml-cpu/ggml-cpu-quants.h +63 -0
  63. data/ext/ggml/src/ggml-cpu/ggml-cpu-traits.cpp +36 -0
  64. data/ext/ggml/src/ggml-cpu/ggml-cpu-traits.h +38 -0
  65. data/ext/ggml/src/ggml-cpu/ggml-cpu.c +14123 -0
  66. data/ext/ggml/src/ggml-cpu/ggml-cpu.cpp +622 -0
  67. data/ext/ggml/src/ggml-cpu/llamafile/sgemm.cpp +1884 -0
  68. data/ext/ggml/src/ggml-cpu/llamafile/sgemm.h +14 -0
  69. data/ext/ggml/src/ggml-cuda/vendors/cuda.h +14 -0
  70. data/ext/ggml/src/ggml-cuda/vendors/hip.h +186 -0
  71. data/ext/ggml/src/ggml-cuda/vendors/musa.h +134 -0
  72. data/ext/ggml/src/ggml-impl.h +556 -0
  73. data/ext/ggml/src/ggml-kompute/ggml-kompute.cpp +2251 -0
  74. data/ext/ggml/src/ggml-metal/ggml-metal-impl.h +288 -0
  75. data/ext/ggml/src/ggml-metal/ggml-metal.m +4884 -0
  76. data/ext/ggml/src/ggml-metal/ggml-metal.metal +6732 -0
  77. data/ext/ggml/src/ggml-opt.cpp +854 -0
  78. data/ext/ggml/src/ggml-quants.c +5238 -0
  79. data/ext/ggml/src/ggml-quants.h +100 -0
  80. data/ext/ggml/src/ggml-rpc/ggml-rpc.cpp +1406 -0
  81. data/ext/ggml/src/ggml-sycl/common.cpp +95 -0
  82. data/ext/ggml/src/ggml-sycl/concat.cpp +196 -0
  83. data/ext/ggml/src/ggml-sycl/conv.cpp +99 -0
  84. data/ext/ggml/src/ggml-sycl/convert.cpp +547 -0
  85. data/ext/ggml/src/ggml-sycl/dmmv.cpp +1023 -0
  86. data/ext/ggml/src/ggml-sycl/element_wise.cpp +1030 -0
  87. data/ext/ggml/src/ggml-sycl/ggml-sycl.cpp +4729 -0
  88. data/ext/ggml/src/ggml-sycl/im2col.cpp +126 -0
  89. data/ext/ggml/src/ggml-sycl/mmq.cpp +3031 -0
  90. data/ext/ggml/src/ggml-sycl/mmvq.cpp +1015 -0
  91. data/ext/ggml/src/ggml-sycl/norm.cpp +378 -0
  92. data/ext/ggml/src/ggml-sycl/outprod.cpp +56 -0
  93. data/ext/ggml/src/ggml-sycl/rope.cpp +276 -0
  94. data/ext/ggml/src/ggml-sycl/softmax.cpp +251 -0
  95. data/ext/ggml/src/ggml-sycl/tsembd.cpp +72 -0
  96. data/ext/ggml/src/ggml-sycl/wkv6.cpp +141 -0
  97. data/ext/ggml/src/ggml-threading.cpp +12 -0
  98. data/ext/ggml/src/ggml-threading.h +14 -0
  99. data/ext/ggml/src/ggml-vulkan/ggml-vulkan.cpp +8657 -0
  100. data/ext/ggml/src/ggml-vulkan/vulkan-shaders/vulkan-shaders-gen.cpp +593 -0
  101. data/ext/ggml/src/ggml.c +7694 -0
  102. data/ext/{whisper.h → include/whisper.h} +23 -22
  103. data/ext/metal-embed.mk +17 -0
  104. data/ext/metal.mk +6 -0
  105. data/ext/ruby_whisper.cpp +1492 -9
  106. data/ext/ruby_whisper.h +10 -0
  107. data/ext/scripts/get-flags.mk +38 -0
  108. data/ext/src/coreml/whisper-decoder-impl.h +146 -0
  109. data/ext/src/coreml/whisper-decoder-impl.m +201 -0
  110. data/ext/src/coreml/whisper-encoder-impl.h +142 -0
  111. data/ext/src/coreml/whisper-encoder-impl.m +197 -0
  112. data/ext/src/coreml/whisper-encoder.h +26 -0
  113. data/ext/src/openvino/whisper-openvino-encoder.cpp +108 -0
  114. data/ext/src/openvino/whisper-openvino-encoder.h +31 -0
  115. data/ext/{whisper.cpp → src/whisper.cpp} +661 -492
  116. data/extsources.rb +6 -0
  117. data/lib/whisper/model/uri.rb +157 -0
  118. data/lib/whisper.rb +2 -0
  119. data/tests/helper.rb +7 -0
  120. data/tests/jfk_reader/.gitignore +5 -0
  121. data/tests/jfk_reader/extconf.rb +3 -0
  122. data/tests/jfk_reader/jfk_reader.c +68 -0
  123. data/tests/test_callback.rb +160 -0
  124. data/tests/test_error.rb +20 -0
  125. data/tests/test_model.rb +71 -0
  126. data/tests/test_package.rb +31 -0
  127. data/tests/test_params.rb +160 -0
  128. data/tests/test_segment.rb +83 -0
  129. data/tests/test_whisper.rb +211 -123
  130. data/whispercpp.gemspec +36 -0
  131. metadata +137 -11
  132. data/ext/ggml.c +0 -21755
@@ -0,0 +1,4729 @@
1
+ //
2
+ // MIT license
3
+ // Copyright (C) 2024 Intel Corporation
4
+ // SPDX-License-Identifier: MIT
5
+ //
6
+
7
+ //
8
+ // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
9
+ // See https://llvm.org/LICENSE.txt for license information.
10
+ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
11
+ //
12
+
13
+ #include <algorithm>
14
+ #include <assert.h>
15
+ #include <atomic>
16
+ #include <cinttypes>
17
+ #include <cstddef>
18
+ #include <cstdint>
19
+ #include <cstdlib>
20
+ #include <float.h>
21
+ #include <limits>
22
+ #include <stdint.h>
23
+ #include <stdio.h>
24
+ #include <vector>
25
+ #include <cmath>
26
+ #include <iostream>
27
+ #include <fstream>
28
+ #include <stdio.h>
29
+ #include <stdlib.h>
30
+ #include <regex>
31
+
32
+ #include <sycl/sycl.hpp>
33
+ #include <sycl/half_type.hpp>
34
+
35
+ #include "ggml-sycl.h"
36
+ #include "ggml-impl.h"
37
+ #include "ggml-backend-impl.h"
38
+
39
+ #include "ggml-sycl/backend.hpp"
40
+ #include "ggml-sycl/presets.hpp"
41
+ #include "ggml-sycl/gemm.hpp"
42
+
43
+ static bool g_sycl_loaded = false;
44
+
45
+ static ggml_sycl_device_info ggml_sycl_init() {
46
+ ggml_sycl_device_info info = {};
47
+
48
+ info.device_count = dpct::dev_mgr::instance().device_count();
49
+ if (info.device_count == 0) {
50
+ GGML_LOG_ERROR("%s: failed to initialize: %s\n", GGML_SYCL_NAME, __func__);
51
+ return info;
52
+ }
53
+
54
+ GGML_ASSERT(info.device_count <= GGML_SYCL_MAX_DEVICES);
55
+
56
+ int64_t total_vram = 0;
57
+ #if defined(GGML_SYCL_FORCE_MMQ)
58
+ GGML_LOG_INFO("%s: GGML_SYCL_FORCE_MMQ: yes\n", __func__);
59
+ #else
60
+ GGML_LOG_INFO("%s: GGML_SYCL_FORCE_MMQ: no\n", __func__);
61
+ #endif
62
+ #if defined(SYCL_USE_XMX)
63
+ GGML_LOG_INFO("%s: SYCL_USE_XMX: yes\n", __func__);
64
+ #else
65
+ GGML_LOG_INFO("%s: SYCL_USE_XMX: no\n", __func__);
66
+ #endif
67
+ GGML_LOG_INFO("%s: found %d %s devices:\n", __func__, info.device_count, GGML_SYCL_NAME);
68
+
69
+ for (int i = 0; i < info.device_count; ++i) {
70
+ info.devices[i].vmm = 0;
71
+ dpct::device_info prop;
72
+ SYCL_CHECK(CHECK_TRY_ERROR(dpct::get_device_info(
73
+ prop, dpct::dev_mgr::instance().get_device(i))));
74
+
75
+ info.default_tensor_split[i] = total_vram;
76
+ total_vram += prop.get_global_mem_size();
77
+
78
+ info.devices[i].cc =
79
+ 100 * prop.get_major_version() + 10 * prop.get_minor_version();
80
+
81
+ info.max_work_group_sizes[i] = prop.get_max_work_group_size();
82
+ }
83
+
84
+ for (int id = 0; id < info.device_count; ++id) {
85
+ info.default_tensor_split[id] /= total_vram;
86
+ }
87
+ return info;
88
+ }
89
+
90
+ const ggml_sycl_device_info & ggml_sycl_info() {
91
+ static ggml_sycl_device_info info = ggml_sycl_init();
92
+ return info;
93
+ }
94
+
95
+ void print_device_detail(int id, sycl::device &device, std::string device_type) {
96
+
97
+ dpct::device_info prop;
98
+ SYCL_CHECK(CHECK_TRY_ERROR(
99
+ dpct::get_device_info(prop, device)));
100
+
101
+ std::string version;
102
+ version += std::to_string(prop.get_major_version());
103
+ version += ".";
104
+ version += std::to_string(prop.get_minor_version());
105
+
106
+ device_type = std::regex_replace(device_type, std::regex("ext_oneapi_"), "");
107
+ std::string name = std::string(prop.get_name());
108
+ name = std::regex_replace(name, std::regex("\\(R\\)"), "");
109
+ name = std::regex_replace(name, std::regex("\\(TM\\)"), "");
110
+
111
+ auto global_mem_size = prop.get_global_mem_size()/1000000;
112
+
113
+ GGML_LOG_INFO("|%2d|%19s|%39s|%7s|%7d|%8d|%5d|%6luM|%21s|\n", id, device_type.c_str(),
114
+ name.c_str(), version.c_str(), prop.get_max_compute_units(),
115
+ prop.get_max_work_group_size(), prop.get_max_sub_group_size(),
116
+ global_mem_size, device.get_info<sycl::info::device::driver_version>().c_str());
117
+ }
118
+
119
+ void ggml_backend_sycl_print_sycl_devices() {
120
+ GGML_SYCL_DEBUG("[SYCL] call ggml_backend_sycl_print_sycl_devices\n");
121
+ int device_count = dpct::dev_mgr::instance().device_count();
122
+ std::map<std::string, size_t> DeviceNums;
123
+ GGML_LOG_INFO("Found %d SYCL devices:\n", device_count);
124
+
125
+ GGML_LOG_INFO(
126
+ "| | | | "
127
+ " |Max | |Max |Global | |\n");
128
+ GGML_LOG_INFO(
129
+ "| | | | "
130
+ " |compute|Max work|sub |mem | |\n");
131
+ GGML_LOG_INFO(
132
+ "|ID| Device Type| "
133
+ "Name|Version|units |group |group|size | Driver version|\n");
134
+ GGML_LOG_INFO(
135
+ "|--|-------------------|---------------------------------------|------"
136
+ "-|-------|--------|-----|-------|---------------------|\n");
137
+
138
+ for (int id = 0; id < device_count; ++id) {
139
+ sycl::device device = dpct::dev_mgr::instance().get_device(id);
140
+ std::string backend_type = get_device_backend_and_type(device);
141
+ int type_id = DeviceNums[backend_type]++;
142
+ std::stringstream device_type;
143
+ device_type << "[" << backend_type << ":" << std::to_string(type_id)
144
+ << "]";
145
+ print_device_detail(id, device, device_type.str());
146
+ }
147
+ }
148
+
149
+ static inline int get_sycl_env(const char *env_name, int default_val) {
150
+ char *user_device_string = getenv(env_name);
151
+ int user_number = default_val;
152
+
153
+ unsigned n;
154
+ if (user_device_string != NULL &&
155
+ sscanf(user_device_string, " %u", &n) == 1) {
156
+ user_number = (int)n;
157
+ } else {
158
+ user_number = default_val;
159
+ }
160
+ return user_number;
161
+ }
162
+
163
+ static void ggml_check_sycl() try {
164
+ static bool initialized = false;
165
+
166
+ if (!initialized) {
167
+ GGML_LOG_INFO("[SYCL] call ggml_check_sycl\n");
168
+ g_ggml_sycl_debug = get_sycl_env("GGML_SYCL_DEBUG", 0);
169
+ GGML_LOG_INFO("%s: GGML_SYCL_DEBUG: %d\n", __func__, g_ggml_sycl_debug);
170
+
171
+ #if defined(GGML_SYCL_F16)
172
+ GGML_LOG_INFO("%s: GGML_SYCL_F16: yes\n", __func__);
173
+ #else
174
+ GGML_LOG_INFO("%s: GGML_SYCL_F16: no\n", __func__);
175
+ #endif
176
+
177
+ /* NOT REMOVE, keep it for next optimize for XMX.
178
+ #if defined(SYCL_USE_XMX)
179
+ fprintf(stderr, "%s: SYCL_USE_XMX: yes\n", __func__);
180
+ #else
181
+ fprintf(stderr, "%s: SYCL_USE_XMX: no\n", __func__);
182
+ #endif
183
+ */
184
+
185
+ if (CHECK_TRY_ERROR(g_all_sycl_device_count =
186
+ dpct::dev_mgr::instance().device_count()) != 0) {
187
+ initialized = true;
188
+ g_sycl_loaded = false;
189
+ return;
190
+ }
191
+ GGML_ASSERT(g_all_sycl_device_count <= GGML_SYCL_MAX_DEVICES);
192
+
193
+ initialized = true;
194
+ g_sycl_loaded = true;
195
+ ggml_backend_sycl_print_sycl_devices();
196
+ }
197
+ }
198
+ catch (sycl::exception const &exc) {
199
+ std::cerr << exc.what() << "Exception caught at file:" << __FILE__
200
+ << ", line:" << __LINE__ << std::endl;
201
+ std::exit(1);
202
+ }
203
+
204
+ /*
205
+ device_index: device index from 0 to n (continue numbers).
206
+ It is used for device select/set in SYCL backend internal data structure.
207
+ */
208
+ inline void check_allow_gpu_index(const int device_index) {
209
+ if (device_index >= ggml_sycl_info().device_count) {
210
+ char error_buf[256];
211
+ snprintf(
212
+ error_buf,
213
+ sizeof(error_buf),
214
+ "%s error: device_index:%d is out of range: [0-%d]",
215
+ __func__,
216
+ device_index,
217
+ ggml_sycl_info().device_count - 1);
218
+ GGML_LOG_ERROR("%s\n", error_buf);
219
+ assert(false);
220
+ }
221
+ }
222
+
223
+ GGML_API void ggml_backend_sycl_get_gpu_list(int *id_list, int max_len) try {
224
+ GGML_SYCL_DEBUG("[SYCL] call ggml_backend_sycl_get_gpu_list\n");
225
+ for(int i=0;i<max_len;i++) id_list[i] = -1;
226
+
227
+ for (int i=0;i< ggml_sycl_info().device_count;i++){
228
+ if (i>=max_len) break;
229
+ id_list[i] = i;
230
+ }
231
+ return;
232
+ }
233
+ catch (sycl::exception const &exc) {
234
+ std::cerr << exc.what() << "Exception caught at file:" << __FILE__
235
+ << ", line:" << __LINE__ << std::endl;
236
+ std::exit(1);
237
+ }
238
+
239
+ // sycl buffer
240
+
241
+ struct ggml_backend_sycl_buffer_context {
242
+ int device;
243
+ void * dev_ptr = nullptr;
244
+ queue_ptr stream;
245
+ std::string name;
246
+
247
+ ggml_backend_sycl_buffer_context(int device, void * dev_ptr, queue_ptr stream) :
248
+ device(device), dev_ptr(dev_ptr), stream(stream) {
249
+ check_allow_gpu_index(device);
250
+ name = (GGML_SYCL_NAME + std::to_string(device));
251
+ }
252
+
253
+
254
+ ~ggml_backend_sycl_buffer_context() {
255
+ if (dev_ptr != nullptr) {
256
+ ggml_sycl_set_device(device);
257
+ SYCL_CHECK(CHECK_TRY_ERROR(sycl::free(dev_ptr, *stream)));
258
+ }
259
+ }
260
+ };
261
+
262
+ static const char * ggml_backend_sycl_buffer_type_get_name(ggml_backend_buffer_type_t buft);
263
+
264
+ static bool ggml_backend_buffer_is_sycl(ggml_backend_buffer_t buffer) {
265
+ return buffer->buft->iface.get_name == ggml_backend_sycl_buffer_type_get_name;
266
+ }
267
+
268
+ static void
269
+ ggml_backend_sycl_buffer_free_buffer(ggml_backend_buffer_t buffer) try {
270
+ ggml_backend_sycl_buffer_context * ctx = ( ggml_backend_sycl_buffer_context *)buffer->context;
271
+ ggml_sycl_set_device(ctx->device);
272
+
273
+ delete ctx;
274
+ }
275
+ catch (sycl::exception const &exc) {
276
+ std::cerr << exc.what() << "Exception caught at file:" << __FILE__
277
+ << ", line:" << __LINE__ << std::endl;
278
+ std::exit(1);
279
+ }
280
+
281
+ static void * ggml_backend_sycl_buffer_get_base(ggml_backend_buffer_t buffer) {
282
+ ggml_backend_sycl_buffer_context * ctx = ( ggml_backend_sycl_buffer_context *)buffer->context;
283
+ return ctx->dev_ptr;
284
+ }
285
+
286
+ static void
287
+ ggml_backend_sycl_buffer_init_tensor(ggml_backend_buffer_t buffer,
288
+ ggml_tensor *tensor) try {
289
+ ggml_backend_sycl_buffer_context * ctx = (ggml_backend_sycl_buffer_context *)buffer->context;
290
+
291
+ if (tensor->view_src != NULL && tensor->view_offs == 0) {
292
+ assert(tensor->view_src->buffer->buft == buffer->buft);
293
+ tensor->backend = tensor->view_src->backend;
294
+ tensor->extra = tensor->view_src->extra;
295
+ return;
296
+ }
297
+
298
+
299
+ if (ggml_is_quantized(tensor->type)) {
300
+ // initialize padding to 0 to avoid possible NaN values
301
+ size_t original_size = ggml_nbytes(tensor);
302
+ size_t padded_size = ggml_backend_buft_get_alloc_size(buffer->buft, tensor);
303
+
304
+ if (padded_size > original_size && tensor->view_src == nullptr) {
305
+ SYCL_CHECK(CHECK_TRY_ERROR(ctx->stream->memset(
306
+ (char *)tensor->data + original_size, 0,
307
+ padded_size - original_size).wait()));
308
+ }
309
+ }
310
+ }
311
+ catch (sycl::exception const &exc) {
312
+ std::cerr << exc.what() << "Exception caught at file:" << __FILE__
313
+ << ", line:" << __LINE__ << std::endl;
314
+ std::exit(1);
315
+ }
316
+
317
+ static void ggml_backend_sycl_buffer_set_tensor(ggml_backend_buffer_t buffer,
318
+ ggml_tensor *tensor,
319
+ const void *data, size_t offset,
320
+ size_t size) try {
321
+
322
+ ggml_backend_sycl_buffer_context * ctx = ( ggml_backend_sycl_buffer_context *)buffer->context;
323
+
324
+ ggml_sycl_set_device(ctx->device);
325
+ auto stream = &(dpct::dev_mgr::instance().get_device(ctx->device).default_queue());
326
+ SYCL_CHECK(
327
+ CHECK_TRY_ERROR(dpct::dev_mgr::instance().get_device(ctx->device).queues_wait_and_throw()));
328
+ char* host_buf = (char*)malloc(size);
329
+ memcpy(host_buf, data, size);
330
+ SYCL_CHECK(
331
+ CHECK_TRY_ERROR((*stream).memcpy((char *)tensor->data + offset, host_buf, size)
332
+ .wait()));
333
+ free(host_buf);
334
+ }
335
+ catch (sycl::exception const &exc) {
336
+ std::cerr << exc.what() << "Exception caught at file:" << __FILE__
337
+ << ", line:" << __LINE__ << std::endl;
338
+ std::exit(1);
339
+ }
340
+
341
+ static void ggml_backend_sycl_buffer_get_tensor(ggml_backend_buffer_t buffer,
342
+ const ggml_tensor *tensor,
343
+ void *data, size_t offset,
344
+ size_t size) try {
345
+
346
+ ggml_backend_sycl_buffer_context * ctx = ( ggml_backend_sycl_buffer_context *)buffer->context;
347
+
348
+ ggml_sycl_set_device(ctx->device);
349
+ auto stream = dpct::dev_mgr::instance().get_device(ctx->device).default_queue();
350
+
351
+ SYCL_CHECK(CHECK_TRY_ERROR(
352
+ stream.memcpy(data, (const char *)tensor->data + offset, size)
353
+ .wait()));
354
+ }
355
+ catch (sycl::exception const &exc) {
356
+ std::cerr << exc.what() << "Exception caught at file:" << __FILE__
357
+ << ", line:" << __LINE__ << std::endl;
358
+ std::exit(1);
359
+ }
360
+
361
+ void dev2dev_memcpy(sycl::queue &q_dst, sycl::queue &q_src, void *ptr_dst,
362
+ const void *ptr_src, size_t size) {
363
+ char *host_buf = (char *)malloc(size);
364
+ q_src.memcpy(host_buf, (const char *)ptr_src, size).wait();
365
+ q_dst.memcpy((char *)ptr_dst, host_buf, size).wait();
366
+ free(host_buf);
367
+ }
368
+
369
+ static bool
370
+ ggml_backend_sycl_buffer_cpy_tensor(ggml_backend_buffer_t buffer,
371
+ const ggml_tensor *src,
372
+ ggml_tensor *dst) try {
373
+ if (ggml_backend_buffer_is_sycl(src->buffer)) {
374
+ ggml_backend_sycl_buffer_context * src_ctx = (ggml_backend_sycl_buffer_context *)src->buffer->context;
375
+ ggml_backend_sycl_buffer_context * dst_ctx = (ggml_backend_sycl_buffer_context *)dst->buffer->context;
376
+
377
+ ggml_sycl_set_device(src_ctx->device);
378
+ /*
379
+ DPCT1009:198: SYCL uses exceptions to report errors and does not use the
380
+ error codes. The original code was commented out and a warning string
381
+ was inserted. You need to rewrite this code.
382
+ */
383
+ SYCL_CHECK(CHECK_TRY_ERROR(
384
+ dpct::dev_mgr::instance().get_device(src_ctx->device).queues_wait_and_throw()));
385
+ ggml_sycl_set_device(dst_ctx->device);
386
+ /*
387
+ DPCT1009:199: SYCL uses exceptions to report errors and does not use the
388
+ error codes. The original code was commented out and a warning string
389
+ was inserted. You need to rewrite this code.
390
+ */
391
+ SYCL_CHECK(CHECK_TRY_ERROR(
392
+ dpct::dev_mgr::instance().get_device(dst_ctx->device).queues_wait_and_throw()));
393
+ /*
394
+ DPCT1009:200: SYCL uses exceptions to report errors and does not use the
395
+ error codes. The original code was commented out and a warning string
396
+ was inserted. You need to rewrite this code.
397
+ */
398
+
399
+ queue_ptr stream_dst = dst_ctx->stream;
400
+ queue_ptr stream_src = src_ctx->stream;
401
+ size_t size = ggml_nbytes(src);
402
+
403
+ //todo. it's dirty solutino to walkaroud known issue:device2device cross GPUs.
404
+ dev2dev_memcpy(*stream_dst, *stream_src, dst->data, src->data, size);
405
+
406
+ //todo, it's known issue:error in device2device cross GPUs. reused when the issue is fixed. DON"T remove
407
+ #if 0
408
+ SYCL_CHECK(CHECK_TRY_ERROR((*stream).memcpy(
409
+ (char *)dst->data, (const char *)src->data, size).wait()));
410
+
411
+ /*
412
+ DPCT1009:201: SYCL uses exceptions to report errors and does not use the
413
+ error codes. The original code was commented out and a warning string
414
+ was inserted. You need to rewrite this code.
415
+ */
416
+ SYCL_CHECK(CHECK_TRY_ERROR(
417
+ dpct::dev_mgr::instance().get_device(dst_ctx->device).queues_wait_and_throw()));
418
+ #endif
419
+ return true;
420
+ }
421
+ return false;
422
+ GGML_UNUSED(buffer);
423
+ } catch (const sycl::exception & exc) {
424
+ std::cerr << exc.what() << "Exception caught at file:" << __FILE__ << ", line:" << __LINE__ << std::endl;
425
+ std::exit(1);
426
+ }
427
+
428
+ static void ggml_backend_sycl_buffer_clear(ggml_backend_buffer_t buffer,
429
+ uint8_t value) try {
430
+ ggml_backend_sycl_buffer_context * ctx = ( ggml_backend_sycl_buffer_context *)buffer->context;
431
+
432
+ ggml_sycl_set_device(ctx->device);
433
+ queue_ptr stream = ctx->stream;
434
+ SYCL_CHECK(
435
+ CHECK_TRY_ERROR(dpct::get_current_device().queues_wait_and_throw()));
436
+
437
+ SYCL_CHECK(CHECK_TRY_ERROR((*stream)
438
+ .memset(ctx->dev_ptr, value, buffer->size)
439
+ .wait()));
440
+ }
441
+ catch (sycl::exception const &exc) {
442
+ std::cerr << exc.what() << "Exception caught at file:" << __FILE__
443
+ << ", line:" << __LINE__ << std::endl;
444
+ std::exit(1);
445
+ }
446
+
447
+ static const ggml_backend_buffer_i ggml_backend_sycl_buffer_interface = {
448
+ /* .free_buffer = */ ggml_backend_sycl_buffer_free_buffer,
449
+ /* .get_base = */ ggml_backend_sycl_buffer_get_base,
450
+ /* .init_tensor = */ ggml_backend_sycl_buffer_init_tensor,
451
+ /* .memset_tensor = */ NULL,
452
+ /* .set_tensor = */ ggml_backend_sycl_buffer_set_tensor,
453
+ /* .get_tensor = */ ggml_backend_sycl_buffer_get_tensor,
454
+ /* .cpy_tensor = */ ggml_backend_sycl_buffer_cpy_tensor,
455
+ /* .clear = */ ggml_backend_sycl_buffer_clear,
456
+ /* .reset = */ NULL,
457
+ };
458
+
459
+ // sycl buffer type
460
+ struct ggml_backend_sycl_buffer_type_context {
461
+ int device;
462
+ std::string name;
463
+
464
+ // each buffer type has its own stream
465
+ queue_ptr stream = nullptr;
466
+ };
467
+
468
+ static const char * ggml_backend_sycl_buffer_type_get_name(ggml_backend_buffer_type_t buft) {
469
+ ggml_backend_sycl_buffer_type_context * ctx = (ggml_backend_sycl_buffer_type_context *)buft->context;
470
+
471
+ return ctx->name.c_str();
472
+ }
473
+
474
+ static ggml_backend_buffer_t
475
+ ggml_backend_sycl_buffer_type_alloc_buffer(ggml_backend_buffer_type_t buft,
476
+ size_t size) try {
477
+ ggml_backend_sycl_buffer_type_context * buft_ctx = (ggml_backend_sycl_buffer_type_context *)buft->context;
478
+ ggml_sycl_set_device(buft_ctx->device);
479
+ const queue_ptr stream = buft_ctx->stream;
480
+ size = std::max(size, (size_t)1); // syclMalloc returns null for size 0
481
+
482
+ void * dev_ptr;
483
+ SYCL_CHECK(CHECK_TRY_ERROR(dev_ptr = (void *)sycl::malloc_device(
484
+ size, *stream)));
485
+ if (!dev_ptr) {
486
+ GGML_LOG_ERROR("%s: can't allocate %lu Bytes of memory on device\n", __func__, size);
487
+ return nullptr;
488
+ }
489
+ ggml_backend_sycl_buffer_context * ctx = new ggml_backend_sycl_buffer_context(buft_ctx->device, dev_ptr, buft_ctx->stream);
490
+ return ggml_backend_buffer_init(buft, ggml_backend_sycl_buffer_interface, ctx, size);
491
+ }
492
+ catch (sycl::exception const &exc) {
493
+ std::cerr << exc.what() << "Exception caught at file:" << __FILE__
494
+ << ", line:" << __LINE__ << std::endl;
495
+ std::exit(1);
496
+ }
497
+
498
+ static size_t ggml_backend_sycl_buffer_type_get_alignment(ggml_backend_buffer_type_t buft) {
499
+ return 128;
500
+ GGML_UNUSED(buft);
501
+ }
502
+
503
+ static size_t ggml_backend_sycl_buffer_type_get_max_size(ggml_backend_buffer_type_t buft) {
504
+ return dpct::get_current_device().get_max_mem_alloc_size();
505
+
506
+ GGML_UNUSED(buft);
507
+ }
508
+
509
+ static size_t ggml_backend_sycl_buffer_type_get_alloc_size(ggml_backend_buffer_type_t buft, const ggml_tensor * tensor) {
510
+ size_t size = ggml_nbytes(tensor);
511
+ int64_t ne0 = tensor->ne[0];
512
+
513
+ if (ggml_is_quantized(tensor->type)) {
514
+ if (ne0 % MATRIX_ROW_PADDING != 0) {
515
+ size += ggml_row_size(tensor->type, MATRIX_ROW_PADDING - ne0 % MATRIX_ROW_PADDING);
516
+ }
517
+ }
518
+
519
+ return size;
520
+
521
+ GGML_UNUSED(buft);
522
+ }
523
+
524
+ static const ggml_backend_buffer_type_i ggml_backend_sycl_buffer_type_interface = {
525
+ /* .get_name = */ ggml_backend_sycl_buffer_type_get_name,
526
+ /* .alloc_buffer = */ ggml_backend_sycl_buffer_type_alloc_buffer,
527
+ /* .get_alignment = */ ggml_backend_sycl_buffer_type_get_alignment,
528
+ /* .get_max_size = */ ggml_backend_sycl_buffer_type_get_max_size,
529
+ /* .get_alloc_size = */ ggml_backend_sycl_buffer_type_get_alloc_size,
530
+ /* .is_host = */ NULL,
531
+ };
532
+
533
+ ggml_backend_buffer_type_t ggml_backend_sycl_buffer_type(int device) {
534
+ static std::mutex mutex;
535
+ std::lock_guard<std::mutex> lock(mutex);
536
+
537
+ GGML_SYCL_DEBUG("[SYCL] call ggml_backend_sycl_buffer_type\n");
538
+
539
+ auto dev_count = ggml_backend_sycl_get_device_count();
540
+
541
+ if (device>=dev_count or device<0) {
542
+ printf("ggml_backend_sycl_buffer_type error: device_index:%d is out of range [0, %d], miss to call ggml_backend_sycl_set_single_device()\n",
543
+ device, dev_count-1);
544
+ GGML_ASSERT(device<dev_count);
545
+ }
546
+ static struct ggml_backend_buffer_type ggml_backend_sycl_buffer_types[GGML_SYCL_MAX_DEVICES];
547
+
548
+ static bool ggml_backend_sycl_buffer_type_initialized = false;
549
+
550
+ if (!ggml_backend_sycl_buffer_type_initialized) {
551
+ for (int i = 0; i < dev_count; i++) {
552
+ auto & device_i = dpct::dev_mgr::instance().get_device(i);
553
+ queue_ptr stream = &(device_i.default_queue());
554
+ ggml_backend_sycl_buffer_types[i] = {
555
+ /* .iface = */ ggml_backend_sycl_buffer_type_interface,
556
+ /* .device = */ ggml_backend_reg_dev_get(ggml_backend_sycl_reg(), i),
557
+ /* .context = */ new ggml_backend_sycl_buffer_type_context{i, GGML_SYCL_NAME + std::to_string(i), stream},
558
+ };
559
+ }
560
+ ggml_backend_sycl_buffer_type_initialized = true;
561
+ }
562
+ return &ggml_backend_sycl_buffer_types[device];
563
+ }
564
+
565
+ ggml_backend_buffer_type_t ggml_backend_sycl_buffer_type(ggml_backend_sycl_context * ctx) {
566
+ GGML_SYCL_DEBUG("[SYCL] call ggml_backend_sycl_buffer_type\n");
567
+
568
+ int device = ctx->device;
569
+ if (device>=ggml_sycl_info().device_count or device<0) {
570
+ printf("ggml_backend_sycl_buffer_type error: device_index:%d is out of range [0, %d], miss to call ggml_backend_sycl_set_single_device()\n",
571
+ device, ggml_sycl_info().device_count-1);
572
+ GGML_ASSERT(device<ggml_sycl_info().device_count);
573
+ }
574
+ static struct ggml_backend_buffer_type ggml_backend_sycl_buffer_types[GGML_SYCL_MAX_DEVICES];
575
+
576
+ static bool ggml_backend_sycl_buffer_type_initialized = false;
577
+
578
+ if (!ggml_backend_sycl_buffer_type_initialized) {
579
+ for (int i = 0; i < ggml_sycl_info().device_count; i++) {
580
+ ggml_backend_sycl_buffer_types[i] = {
581
+ /* .iface = */ ggml_backend_sycl_buffer_type_interface,
582
+ /* .device = */ nullptr,
583
+ /* .context = */ new ggml_backend_sycl_buffer_type_context{i, GGML_SYCL_NAME + std::to_string(i), ctx->stream(i, 0)},
584
+ };
585
+ }
586
+ ggml_backend_sycl_buffer_type_initialized = true;
587
+ }
588
+ return &ggml_backend_sycl_buffer_types[device];
589
+ }
590
+
591
+ // sycl split buffer
592
+
593
+ static int64_t get_row_rounding(ggml_type type, const std::array<float, GGML_SYCL_MAX_DEVICES> & tensor_split) {
594
+ int64_t min_compute_capability = INT_MAX;
595
+ int64_t max_compute_capability = INT_MIN;
596
+ for (int i = 0; i < ggml_sycl_info().device_count; ++i) {
597
+ if (tensor_split[i] < (i + 1 < ggml_sycl_info().device_count ? tensor_split[i + 1] : 1.0f)) {
598
+ if (min_compute_capability > ggml_sycl_info().devices[i].cc) {
599
+ min_compute_capability = ggml_sycl_info().devices[i].cc;
600
+ }
601
+ if (max_compute_capability < ggml_sycl_info().devices[i].cc) {
602
+ max_compute_capability = ggml_sycl_info().devices[i].cc;
603
+ }
604
+ }
605
+ }
606
+
607
+ switch(type) {
608
+ case GGML_TYPE_Q4_0:
609
+ case GGML_TYPE_Q4_1:
610
+ return max_compute_capability >= VER_GEN9 ? 128 : 64;
611
+ case GGML_TYPE_Q5_0:
612
+ case GGML_TYPE_Q5_1:
613
+ case GGML_TYPE_Q8_0:
614
+ return 64;
615
+ case GGML_TYPE_F16:
616
+ case GGML_TYPE_F32:
617
+ return 1;
618
+ case GGML_TYPE_Q2_K:
619
+ case GGML_TYPE_Q3_K:
620
+ case GGML_TYPE_Q4_K:
621
+ case GGML_TYPE_Q5_K:
622
+ case GGML_TYPE_IQ2_XXS:
623
+ case GGML_TYPE_IQ2_XS:
624
+ case GGML_TYPE_IQ2_S:
625
+ case GGML_TYPE_IQ1_S:
626
+ case GGML_TYPE_IQ1_M:
627
+ case GGML_TYPE_IQ3_XXS:
628
+ case GGML_TYPE_IQ4_XS:
629
+ case GGML_TYPE_IQ4_NL:
630
+ return max_compute_capability >= VER_GEN9 ? 128 : 64;
631
+ case GGML_TYPE_IQ3_S:
632
+ return max_compute_capability >= VER_GEN9 ? 128 : 64;
633
+ case GGML_TYPE_Q6_K:
634
+ return 64;
635
+ default:
636
+ GGML_ABORT("fatal error");
637
+ }
638
+ }
639
+
640
+ static void get_row_split(int64_t * row_low, int64_t * row_high, const ggml_tensor * tensor, const std::array<float, GGML_SYCL_MAX_DEVICES> & tensor_split, int id) {
641
+ const int64_t nrows = ggml_nrows(tensor);
642
+ const int64_t rounding = get_row_rounding(tensor->type, tensor_split);
643
+
644
+ *row_low = id == 0 ? 0 : nrows*tensor_split[id];
645
+ *row_low -= *row_low % rounding;
646
+ if (id == ggml_sycl_info().device_count - 1) {
647
+ *row_high = nrows;
648
+ } else {
649
+ *row_high = nrows*tensor_split[id + 1];
650
+ *row_high -= *row_high % rounding;
651
+ }
652
+ }
653
+
654
+ static size_t ggml_nbytes_split(const struct ggml_tensor * tensor, int nrows_split) {
655
+ static_assert(GGML_MAX_DIMS == 4, "GGML_MAX_DIMS is not 4 - update this function");
656
+
657
+ return nrows_split*ggml_row_size(tensor->type, tensor->ne[0]);
658
+ }
659
+
660
+ struct ggml_backend_sycl_split_buffer_type_context {
661
+ std::array<float, GGML_SYCL_MAX_DEVICES> tensor_split;
662
+ };
663
+
664
+ struct ggml_backend_sycl_split_buffer_context {
665
+ ~ggml_backend_sycl_split_buffer_context() try {
666
+ for (ggml_tensor_extra_gpu * extra : tensor_extras) {
667
+ for (int i = 0; i < ggml_sycl_info().device_count; ++i) {
668
+ for (int64_t is = 0; is < GGML_SYCL_MAX_STREAMS; ++is) {
669
+ if (extra->events[i][is] != nullptr) {
670
+ /*
671
+ DPCT1009:206: SYCL uses exceptions to report errors and
672
+ does not use the error codes. The original code was
673
+ commented out and a warning string was inserted. You
674
+ need to rewrite this code.
675
+ */
676
+ SYCL_CHECK(CHECK_TRY_ERROR(
677
+ dpct::destroy_event(extra->events[i][is])));
678
+ }
679
+ }
680
+ if (extra->data_device[i] != nullptr) {
681
+ /*
682
+ DPCT1009:207: SYCL uses exceptions to report errors and does
683
+ not use the error codes. The original code was commented out
684
+ and a warning string was inserted. You need to rewrite this
685
+ code.
686
+ */
687
+ ggml_sycl_set_device(i);
688
+ SYCL_CHECK(CHECK_TRY_ERROR(sycl::free(
689
+ extra->data_device[i], *(streams[i]))));
690
+ }
691
+ }
692
+ delete extra;
693
+ }
694
+ }
695
+ catch (sycl::exception const &exc) {
696
+ std::cerr << exc.what() << "Exception caught at file:" << __FILE__
697
+ << ", line:" << __LINE__ << std::endl;
698
+ std::exit(1);
699
+ }
700
+
701
+ std::vector<ggml_tensor_extra_gpu *> tensor_extras;
702
+ std::vector<queue_ptr> streams;
703
+ };
704
+
705
+ static void ggml_backend_sycl_split_buffer_free_buffer(ggml_backend_buffer_t buffer) {
706
+ ggml_backend_sycl_split_buffer_context * ctx = (ggml_backend_sycl_split_buffer_context *)buffer->context;
707
+ delete ctx;
708
+ }
709
+
710
+ static void * ggml_backend_sycl_split_buffer_get_base(ggml_backend_buffer_t buffer) {
711
+ // the pointers are stored in the tensor extras, this is just a dummy address and never dereferenced
712
+ return (void *)0x1000;
713
+
714
+ GGML_UNUSED(buffer);
715
+ }
716
+
717
+ static void
718
+ ggml_backend_sycl_split_buffer_init_tensor(ggml_backend_buffer_t buffer,
719
+ ggml_tensor *tensor) try {
720
+ GGML_ASSERT(tensor->view_src == nullptr); // views of split tensors are not supported
721
+
722
+ ggml_backend_sycl_split_buffer_context * ctx = (ggml_backend_sycl_split_buffer_context *)buffer->context;
723
+ ggml_backend_sycl_split_buffer_type_context * buft_ctx = (ggml_backend_sycl_split_buffer_type_context *)buffer->buft->context;
724
+
725
+ const int64_t ne0 = tensor->ne[0];
726
+
727
+ ggml_tensor_extra_gpu * extra = new ggml_tensor_extra_gpu{};
728
+
729
+ ctx->tensor_extras.push_back(extra);
730
+ ctx->streams.push_back(&(dpct::get_current_device().default_queue()));
731
+
732
+ for (int i = 0; i < ggml_sycl_info().device_count; ++i) {
733
+ int64_t row_low, row_high;
734
+ get_row_split(&row_low, &row_high, tensor, buft_ctx->tensor_split, i);
735
+
736
+ int64_t nrows_split = row_high - row_low;
737
+ if (nrows_split == 0) {
738
+ continue;
739
+ }
740
+
741
+ size_t size = ggml_nbytes_split(tensor, nrows_split);
742
+ const size_t original_size = size;
743
+
744
+ // pad last row to a multiple of 512 elements to avoid out-of-bounds memory accesses
745
+ if (ne0 % MATRIX_ROW_PADDING != 0) {
746
+ size += ggml_row_size(tensor->type, MATRIX_ROW_PADDING - ne0 % MATRIX_ROW_PADDING);
747
+ }
748
+
749
+ // FIXME: do not crash if cudaMalloc fails
750
+ // currently, init_tensor cannot fail, it needs to be fixed in ggml-backend first
751
+ ggml_sycl_set_device(i);
752
+ const queue_ptr stream = ctx->streams[i];
753
+ char * buf;
754
+ /*
755
+ DPCT1009:208: SYCL uses exceptions to report errors and does not use the
756
+ error codes. The original code was commented out and a warning string
757
+ was inserted. You need to rewrite this code.
758
+ */
759
+ SYCL_CHECK(CHECK_TRY_ERROR(buf = (char *)sycl::malloc_device(
760
+ size, *stream)));
761
+ if (!buf) {
762
+ char err_buf[1024];
763
+ snprintf(err_buf, 1023, "%s: can't allocate %lu Bytes of memory on device\n", __func__, size);
764
+ throw std::runtime_error(err_buf);
765
+ }
766
+ // set padding to 0 to avoid possible NaN values
767
+ if (size > original_size) {
768
+ /*
769
+ DPCT1009:209: SYCL uses exceptions to report errors and does not use
770
+ the error codes. The original code was commented out and a warning
771
+ string was inserted. You need to rewrite this code.
772
+ */
773
+ SYCL_CHECK(CHECK_TRY_ERROR(
774
+ (*stream)
775
+ .memset(buf + original_size, 0, size - original_size)
776
+ .wait()));
777
+ }
778
+
779
+ extra->data_device[i] = buf;
780
+
781
+ for (int64_t is = 0; is < GGML_SYCL_MAX_STREAMS; ++is) {
782
+ /*
783
+ DPCT1009:210: SYCL uses exceptions to report errors and does not use
784
+ the error codes. The original code was commented out and a warning
785
+ string was inserted. You need to rewrite this code.
786
+ */
787
+ SYCL_CHECK(
788
+ CHECK_TRY_ERROR(extra->events[i][is] = new sycl::event()));
789
+ }
790
+ }
791
+ tensor->backend = GGML_BACKEND_TYPE_GPU_SPLIT;
792
+ tensor->extra = extra;
793
+ }
794
+ catch (sycl::exception const &exc) {
795
+ std::cerr << exc.what() << "Exception caught at file:" << __FILE__
796
+ << ", line:" << __LINE__ << std::endl;
797
+ std::exit(1);
798
+ }
799
+
800
+ static void
801
+ ggml_backend_sycl_split_buffer_set_tensor(ggml_backend_buffer_t buffer,
802
+ ggml_tensor *tensor, const void *data,
803
+ size_t offset, size_t size) try {
804
+ // split tensors must always be set in their entirety at once
805
+ GGML_ASSERT(offset == 0);
806
+ GGML_ASSERT(size == ggml_nbytes(tensor));
807
+
808
+ ggml_backend_sycl_split_buffer_context * ctx = (ggml_backend_sycl_split_buffer_context *)buffer->context;
809
+ ggml_backend_sycl_split_buffer_type_context * buft_ctx = (ggml_backend_sycl_split_buffer_type_context *)buffer->buft->context;
810
+
811
+ const int64_t ne0 = tensor->ne[0];
812
+ const size_t nb1 = tensor->nb[1];
813
+ ggml_tensor_extra_gpu * extra = (ggml_tensor_extra_gpu *)tensor->extra;
814
+
815
+ for (int i = 0; i < ggml_sycl_info().device_count; ++i) {
816
+ int64_t row_low, row_high;
817
+ get_row_split(&row_low, &row_high, tensor, buft_ctx->tensor_split, i);
818
+
819
+ int64_t nrows_split = row_high - row_low;
820
+ if (nrows_split == 0) {
821
+ continue;
822
+ }
823
+
824
+ const size_t offset_split = row_low*nb1;
825
+ size_t size = ggml_nbytes_split(tensor, nrows_split);
826
+ const size_t original_size = size;
827
+
828
+ // pad last row to a multiple of 512 elements to avoid out-of-bounds memory accesses
829
+ if (ne0 % MATRIX_ROW_PADDING != 0) {
830
+ size += ggml_row_size(tensor->type, MATRIX_ROW_PADDING - ne0 % MATRIX_ROW_PADDING);
831
+ }
832
+
833
+ const char * buf_host = (const char *)data + offset_split;
834
+ /*
835
+ DPCT1009:211: SYCL uses exceptions to report errors and does not use the
836
+ error codes. The original code was commented out and a warning string
837
+ was inserted. You need to rewrite this code.
838
+ */
839
+ ggml_sycl_set_device(i);
840
+ const queue_ptr stream = ctx->streams[i];
841
+ SYCL_CHECK(CHECK_TRY_ERROR(
842
+ (*stream)
843
+ .memcpy(extra->data_device[i], buf_host, original_size)
844
+ .wait()));
845
+ }
846
+ }
847
+ catch (sycl::exception const &exc) {
848
+ std::cerr << exc.what() << "Exception caught at file:" << __FILE__
849
+ << ", line:" << __LINE__ << std::endl;
850
+ std::exit(1);
851
+ }
852
+
853
+ static void
854
+ ggml_backend_sycl_split_buffer_get_tensor(ggml_backend_buffer_t buffer,
855
+ const ggml_tensor *tensor, void *data,
856
+ size_t offset, size_t size) try {
857
+ // split tensors must always be set in their entirety at once
858
+ GGML_ASSERT(offset == 0);
859
+ GGML_ASSERT(size == ggml_nbytes(tensor));
860
+
861
+ ggml_backend_sycl_split_buffer_context * ctx = (ggml_backend_sycl_split_buffer_context *)buffer->context;
862
+ ggml_backend_sycl_split_buffer_type_context * buft_ctx = (ggml_backend_sycl_split_buffer_type_context *)buffer->buft->context;
863
+
864
+ const int64_t ne0 = tensor->ne[0];
865
+ const size_t nb1 = tensor->nb[1];
866
+ ggml_tensor_extra_gpu * extra = (ggml_tensor_extra_gpu *)tensor->extra;
867
+
868
+ for (int i = 0; i < ggml_sycl_info().device_count; ++i) {
869
+ int64_t row_low, row_high;
870
+ get_row_split(&row_low, &row_high, tensor, buft_ctx->tensor_split, i);
871
+
872
+ int64_t nrows_split = row_high - row_low;
873
+ if (nrows_split == 0) {
874
+ continue;
875
+ }
876
+
877
+ const size_t offset_split = row_low*nb1;
878
+ size_t size = ggml_nbytes_split(tensor, nrows_split);
879
+ const size_t original_size = size;
880
+
881
+ // pad last row to a multiple of 512 elements to avoid out-of-bounds memory accesses
882
+ if (ne0 % MATRIX_ROW_PADDING != 0) {
883
+ size += ggml_row_size(tensor->type, MATRIX_ROW_PADDING - ne0 % MATRIX_ROW_PADDING);
884
+ }
885
+
886
+ char * buf_host = (char *)data + offset_split;
887
+ /*
888
+ DPCT1009:212: SYCL uses exceptions to report errors and does not use the
889
+ error codes. The original code was commented out and a warning string
890
+ was inserted. You need to rewrite this code.
891
+ */
892
+ ggml_sycl_set_device(i);
893
+ const queue_ptr stream = ctx->streams[i];
894
+ SYCL_CHECK(CHECK_TRY_ERROR(
895
+ (*stream)
896
+ .memcpy(buf_host, extra->data_device[i], original_size)
897
+ .wait()));
898
+ }
899
+ }
900
+ catch (sycl::exception const &exc) {
901
+ std::cerr << exc.what() << "Exception caught at file:" << __FILE__
902
+ << ", line:" << __LINE__ << std::endl;
903
+ std::exit(1);
904
+ }
905
+
906
+ static void ggml_backend_sycl_split_buffer_clear(ggml_backend_buffer_t buffer, uint8_t value) {
907
+ GGML_UNUSED(buffer);
908
+ GGML_UNUSED(value);
909
+ }
910
+
911
+ static struct ggml_backend_buffer_i ggml_backend_sycl_split_buffer_interface = {
912
+ /* .free_buffer = */ ggml_backend_sycl_split_buffer_free_buffer,
913
+ /* .get_base = */ ggml_backend_sycl_split_buffer_get_base,
914
+ /* .init_tensor = */ ggml_backend_sycl_split_buffer_init_tensor,
915
+ /* .memset_tensor = */ NULL,
916
+ /* .set_tensor = */ ggml_backend_sycl_split_buffer_set_tensor,
917
+ /* .get_tensor = */ ggml_backend_sycl_split_buffer_get_tensor,
918
+ /* .cpy_tensor = */ NULL,
919
+ /* .clear = */ ggml_backend_sycl_split_buffer_clear,
920
+ /* .reset = */ NULL,
921
+ };
922
+
923
+ // sycl split buffer type
924
+
925
+ static const char * ggml_backend_sycl_split_buffer_type_get_name(ggml_backend_buffer_type_t buft) {
926
+ return GGML_SYCL_NAME "_Split";
927
+
928
+ GGML_UNUSED(buft);
929
+ }
930
+
931
+ static bool ggml_backend_buffer_is_sycl_split(ggml_backend_buffer_t buffer) {
932
+ return buffer->buft->iface.get_name == ggml_backend_sycl_split_buffer_type_get_name;
933
+ }
934
+
935
+ static ggml_backend_buffer_t ggml_backend_sycl_split_buffer_type_alloc_buffer(ggml_backend_buffer_type_t buft, size_t size) {
936
+ // since we don't know the exact split after rounding, we cannot allocate the device buffers at this point
937
+ // instead, we allocate them for each tensor separately in init_tensor
938
+ // however, the size still represents the maximum cumulative size of all the device buffers after the tensors are allocated,
939
+ // as returned by get_alloc_size. this limit is enforced during tensor allocation by ggml-alloc, so it must be correct.
940
+ ggml_backend_sycl_split_buffer_context * ctx = new ggml_backend_sycl_split_buffer_context();
941
+
942
+ return ggml_backend_buffer_init(buft, ggml_backend_sycl_split_buffer_interface, ctx, size);
943
+ }
944
+
945
+ static size_t ggml_backend_sycl_split_buffer_type_get_alignment(ggml_backend_buffer_type_t buft) {
946
+ return 128;
947
+ GGML_UNUSED(buft);
948
+ }
949
+
950
+ static size_t ggml_backend_sycl_split_buffer_type_get_alloc_size(ggml_backend_buffer_type_t buft, const ggml_tensor * tensor) {
951
+ ggml_backend_sycl_split_buffer_type_context * ctx = (ggml_backend_sycl_split_buffer_type_context *)buft->context;
952
+
953
+ size_t total_size = 0;
954
+
955
+ const int64_t ne0 = tensor->ne[0];
956
+
957
+ for (int i = 0; i < ggml_sycl_info().device_count; ++i) {
958
+ int64_t row_low, row_high;
959
+ get_row_split(&row_low, &row_high, tensor, ctx->tensor_split, i);
960
+
961
+ int64_t nrows_split = row_high - row_low;
962
+ if (nrows_split == 0) {
963
+ continue;
964
+ }
965
+
966
+ total_size += ggml_nbytes_split(tensor, nrows_split);
967
+
968
+ // pad last row to a multiple of 512 elements to avoid out-of-bounds memory accesses
969
+ if (ne0 % MATRIX_ROW_PADDING != 0) {
970
+ total_size += ggml_row_size(tensor->type, MATRIX_ROW_PADDING - ne0 % MATRIX_ROW_PADDING);
971
+ }
972
+ }
973
+
974
+ return total_size;
975
+ }
976
+
977
+ static bool ggml_backend_sycl_split_buffer_type_is_host(ggml_backend_buffer_type_t buft) {
978
+ return false;
979
+
980
+ GGML_UNUSED(buft);
981
+ }
982
+
983
+ static ggml_backend_buffer_type_i ggml_backend_sycl_split_buffer_type_interface = {
984
+ /* .get_name = */ ggml_backend_sycl_split_buffer_type_get_name,
985
+ /* .alloc_buffer = */ ggml_backend_sycl_split_buffer_type_alloc_buffer,
986
+ /* .get_alignment = */ ggml_backend_sycl_split_buffer_type_get_alignment,
987
+ /* .get_max_size = */ NULL, // defaults to SIZE_MAX
988
+ /* .get_alloc_size = */ ggml_backend_sycl_split_buffer_type_get_alloc_size,
989
+ /* .is_host = */ ggml_backend_sycl_split_buffer_type_is_host,
990
+ };
991
+
992
+ ggml_backend_buffer_type_t ggml_backend_sycl_split_buffer_type(const float * tensor_split) {
993
+ static std::mutex mutex;
994
+ std::lock_guard<std::mutex> lock(mutex);
995
+
996
+ GGML_SYCL_DEBUG("[SYCL] call ggml_backend_sycl_split_buffer_type\n");
997
+ ggml_check_sycl();
998
+ // FIXME: this is not thread safe
999
+ static std::map<std::array<float, GGML_SYCL_MAX_DEVICES>, struct ggml_backend_buffer_type> buft_map;
1000
+
1001
+ std::array<float, GGML_SYCL_MAX_DEVICES> tensor_split_arr = {};
1002
+
1003
+ bool all_zero = tensor_split == nullptr || std::all_of(tensor_split, tensor_split + GGML_SYCL_MAX_DEVICES, [](float x) { return x == 0.0f; });
1004
+ if (all_zero) {
1005
+ tensor_split_arr = ggml_sycl_info().default_tensor_split;
1006
+ } else {
1007
+ float split_sum = 0.0f;
1008
+ for (int i = 0; i < ggml_sycl_info().device_count; ++i) {
1009
+ tensor_split_arr[i] = split_sum;
1010
+ split_sum += tensor_split[i];
1011
+ }
1012
+ for (int i = 0; i < ggml_sycl_info().device_count; ++i) {
1013
+ tensor_split_arr[i] /= split_sum;
1014
+ }
1015
+ }
1016
+
1017
+ auto it = buft_map.find(tensor_split_arr);
1018
+ if (it != buft_map.end()) {
1019
+ return &it->second;
1020
+ }
1021
+
1022
+ struct ggml_backend_buffer_type buft {
1023
+ /* .iface = */ ggml_backend_sycl_split_buffer_type_interface,
1024
+ /* .device = */ ggml_backend_reg_dev_get(ggml_backend_sycl_reg(), 0),
1025
+ /* .context = */ new ggml_backend_sycl_split_buffer_type_context{tensor_split_arr},
1026
+ };
1027
+
1028
+ auto result = buft_map.emplace(tensor_split_arr, buft);
1029
+ return &result.first->second;
1030
+ }
1031
+
1032
+ // host buffer type
1033
+
1034
+ static const char * ggml_backend_sycl_host_buffer_type_name(ggml_backend_buffer_type_t buft) {
1035
+ return GGML_SYCL_NAME "_Host";
1036
+
1037
+ GGML_UNUSED(buft);
1038
+ }
1039
+
1040
+ static void ggml_backend_sycl_host_buffer_free_buffer(ggml_backend_buffer_t buffer) {
1041
+ ggml_sycl_host_free(buffer->context);
1042
+ }
1043
+
1044
+ static ggml_backend_buffer_t ggml_backend_sycl_host_buffer_type_alloc_buffer(ggml_backend_buffer_type_t buft, size_t size) {
1045
+ void * ptr = ggml_sycl_host_malloc(size);
1046
+
1047
+ if (ptr == nullptr) {
1048
+ // fallback to cpu buffer
1049
+ return ggml_backend_buft_alloc_buffer(ggml_backend_cpu_buffer_type(), size);
1050
+ }
1051
+
1052
+ // FIXME: this is a hack to avoid having to implement a new buffer type
1053
+ ggml_backend_buffer_t buffer = ggml_backend_cpu_buffer_from_ptr(ptr, size);
1054
+ buffer->buft = buft;
1055
+ buffer->iface.free_buffer = ggml_backend_sycl_host_buffer_free_buffer;
1056
+
1057
+ return buffer;
1058
+ }
1059
+
1060
+ ggml_backend_buffer_type_t ggml_backend_sycl_host_buffer_type() {
1061
+ GGML_SYCL_DEBUG("[SYCL] call ggml_backend_sycl_host_buffer_type\n");
1062
+ static struct ggml_backend_buffer_type ggml_backend_sycl_buffer_type_host = {
1063
+ /* .iface = */ {
1064
+ /* .get_name = */ ggml_backend_sycl_host_buffer_type_name,
1065
+ /* .alloc_buffer = */ ggml_backend_sycl_host_buffer_type_alloc_buffer,
1066
+ /* .get_alignment = */ ggml_backend_cpu_buffer_type()->iface.get_alignment,
1067
+ /* .get_max_size = */ NULL, // TODO: return device.maxBufferLength
1068
+ /* .get_alloc_size = */ ggml_backend_cpu_buffer_type()->iface.get_alloc_size,
1069
+ /* .is_host = */ ggml_backend_cpu_buffer_type()->iface.is_host,
1070
+ },
1071
+ /* .device = */ ggml_backend_reg_dev_get(ggml_backend_sycl_reg(), 0),
1072
+ /* .context = */ nullptr,
1073
+ };
1074
+
1075
+ return &ggml_backend_sycl_buffer_type_host;
1076
+ }
1077
+
1078
+ // buffer pool for sycl (legacy)
1079
+ struct ggml_sycl_pool_leg : public ggml_sycl_pool {
1080
+ static const int MAX_SYCL_BUFFERS = 256;
1081
+
1082
+ int device;
1083
+ queue_ptr qptr;
1084
+ struct ggml_sycl_buffer {
1085
+ void * ptr = nullptr;
1086
+ size_t size = 0;
1087
+ };
1088
+
1089
+ ggml_sycl_buffer buffer_pool[MAX_SYCL_BUFFERS] = {};
1090
+ size_t pool_size = 0;
1091
+
1092
+ explicit ggml_sycl_pool_leg(queue_ptr qptr_, int device_) : device(device_), qptr(qptr_) {}
1093
+
1094
+ ~ggml_sycl_pool_leg() {
1095
+ for (int i = 0; i < MAX_SYCL_BUFFERS; ++i) {
1096
+ ggml_sycl_buffer & b = buffer_pool[i];
1097
+ if (b.ptr != nullptr) {
1098
+ SYCL_CHECK(CHECK_TRY_ERROR(sycl::free(b.ptr, *qptr)));
1099
+ pool_size -= b.size;
1100
+ }
1101
+ }
1102
+ GGML_ASSERT(pool_size == 0);
1103
+ }
1104
+
1105
+ void * alloc(size_t size, size_t * actual_size) override {
1106
+ #ifdef DEBUG_sycl_MALLOC
1107
+ int nnz = 0;
1108
+ size_t max_size = 0;
1109
+ #endif
1110
+ size_t best_diff = 1ull << 36;
1111
+ int ibest = -1;
1112
+ for (int i = 0; i < MAX_SYCL_BUFFERS; ++i) {
1113
+ ggml_sycl_buffer& b = buffer_pool[i];
1114
+ if (b.ptr != nullptr) {
1115
+ #ifdef DEBUG_sycl_MALLOC
1116
+ ++nnz;
1117
+ if (b.size > max_size) max_size = b.size;
1118
+ #endif
1119
+ if (b.size >= size) {
1120
+ size_t diff = b.size - size;
1121
+ if (diff < best_diff) {
1122
+ best_diff = diff;
1123
+ ibest = i;
1124
+ if (!best_diff) {
1125
+ void * ptr = b.ptr;
1126
+ *actual_size = b.size;
1127
+ b.ptr = nullptr;
1128
+ b.size = 0;
1129
+ return ptr;
1130
+ }
1131
+ }
1132
+ }
1133
+ }
1134
+ }
1135
+ if (ibest >= 0) {
1136
+ ggml_sycl_buffer& b = buffer_pool[ibest];
1137
+ void * ptr = b.ptr;
1138
+ *actual_size = b.size;
1139
+ b.ptr = nullptr;
1140
+ b.size = 0;
1141
+ return ptr;
1142
+ }
1143
+ void * ptr;
1144
+ size_t look_ahead_size = (size_t) (1.05 * size);
1145
+
1146
+ SYCL_CHECK(
1147
+ CHECK_TRY_ERROR(ptr = (void *)sycl::malloc_device(
1148
+ look_ahead_size, *qptr)));
1149
+ if (!ptr) {
1150
+ GGML_LOG_ERROR("%s: can't allocate %lu Bytes of memory on device/GPU\n", __func__, look_ahead_size);
1151
+ return nullptr;
1152
+ }
1153
+
1154
+ *actual_size = look_ahead_size;
1155
+ pool_size += look_ahead_size;
1156
+
1157
+ #ifdef DEBUG_SYCL_MALLOC
1158
+ GGML_LOG_DEBUG("%s[%d]: %d buffers, max_size = %u MB, pool_size = %u MB, requested %u MB\n", __func__, id, nnz,
1159
+ (uint32_t)(max_size/1024/1024), (uint32_t)(g_sycl_pool_size[id]/1024/1024), (uint32_t)(size/1024/1024));
1160
+ #endif
1161
+
1162
+ // GGML_SYCL_DEBUG("ggml_sycl_pool_malloc_leg look_ahead_size=%lu, return %p\n", look_ahead_size, ptr);
1163
+ return ptr;
1164
+ }
1165
+
1166
+ void free(void * ptr, size_t size) override {
1167
+ for (int i = 0; i < MAX_SYCL_BUFFERS; ++i) {
1168
+ ggml_sycl_buffer& b = buffer_pool[i];
1169
+ if (b.ptr == nullptr) {
1170
+ b.ptr = ptr;
1171
+ b.size = size;
1172
+ return;
1173
+ }
1174
+ }
1175
+ GGML_LOG_WARN("WARNING: sycl buffer pool full, increase MAX_sycl_BUFFERS\n");
1176
+ SYCL_CHECK(CHECK_TRY_ERROR(sycl::free(ptr, *qptr)));
1177
+ pool_size -= size;
1178
+ }
1179
+ };
1180
+
1181
+ std::unique_ptr<ggml_sycl_pool> ggml_backend_sycl_context::new_pool_for_device(queue_ptr qptr, int device) {
1182
+ // TBD: NO VMM support
1183
+ // if (ggml_sycl_info().devices[device].vmm) {
1184
+ // return std::unique_ptr<ggml_sycl_pool>(new ggml_sycl_pool_vmm(device));
1185
+ // }
1186
+ return std::unique_ptr<ggml_sycl_pool>(new ggml_sycl_pool_leg(qptr, device));
1187
+ }
1188
+
1189
+ // TBD pool with virtual memory management
1190
+ // struct ggml_sycl_pool_vmm : public ggml_sycl_pool
1191
+
1192
+ /// kernels
1193
+
1194
+ typedef void (*cpy_kernel_t)(const char * cx, char * cdst);
1195
+ typedef void (*ggml_sycl_func_t)(ggml_backend_sycl_context & ctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst);
1196
+ typedef void (*ggml_sycl_op_mul_mat_t)(
1197
+ ggml_backend_sycl_context & ctx,
1198
+ const ggml_tensor *src0, const ggml_tensor *src1, ggml_tensor *dst,
1199
+ const char *src0_dd_i, const float *src1_ddf_i, const char *src1_ddq_i,
1200
+ float *dst_dd_i, const int64_t row_low, const int64_t row_high,
1201
+ const int64_t src1_ncols, const int64_t src1_padded_row_size,
1202
+ const queue_ptr &stream);
1203
+
1204
+
1205
+
1206
+ template<int QUANT_BLOCK_TILE>
1207
+ static void quantize_q8_1(const float * __restrict__ x, void * __restrict__ vy, const int kx, const int kx_padded,
1208
+ const sycl::nd_item<3> &item_ct1) {
1209
+ const int ix = (item_ct1.get_local_range(2) * item_ct1.get_group(2) +
1210
+ item_ct1.get_local_id(2)) * QUANT_BLOCK_TILE;
1211
+
1212
+ if (ix >= kx_padded) {
1213
+ return;
1214
+ }
1215
+
1216
+ const int iy = item_ct1.get_local_range(1) * item_ct1.get_group(1) +
1217
+ item_ct1.get_local_id(1);
1218
+
1219
+ const int i_padded = iy*kx_padded + ix;
1220
+
1221
+ block_q8_1 * y = (block_q8_1 *) vy;
1222
+
1223
+ const int ib = i_padded / QK8_1; // block index
1224
+ const int iqs = i_padded % QK8_1; // quant index
1225
+ typedef sycl::vec<float, QUANT_BLOCK_TILE> TC;
1226
+ typedef sycl::vec<int8_t, QUANT_BLOCK_TILE> TQ;
1227
+ TC zeros;
1228
+ TQ qzeros;
1229
+ #pragma unroll
1230
+ for (int i = 0; i < QUANT_BLOCK_TILE; i++)
1231
+ {
1232
+ zeros[i] = 0.f;
1233
+ qzeros[i] = 0;
1234
+ }
1235
+ const TC xi = ix < kx ? *(const TC *)&x[iy * kx + ix] : zeros;
1236
+ float sum = xi[0];
1237
+ float amax = sycl::fabs(xi[0]);
1238
+ #pragma unroll
1239
+ for (int i = 1; i < QUANT_BLOCK_TILE; i++)
1240
+ {
1241
+ sum += xi[i];
1242
+ amax = sycl::fmax(sycl::fabs(xi[i]), amax);
1243
+ }
1244
+ sum = warp_reduce_sum(sum, item_ct1);
1245
+ amax = warp_reduce_max(amax, item_ct1);
1246
+
1247
+ const float d = amax / 127;
1248
+ TQ q = qzeros;
1249
+ if (amax != 0.0f)
1250
+ {
1251
+ #pragma unroll
1252
+ for (int i = 0; i < QUANT_BLOCK_TILE; i++) {
1253
+ q[i] = sycl::round(xi[i] / d);
1254
+ }
1255
+ }
1256
+
1257
+ *(TQ *)&y[ib].qs[iqs] = q;
1258
+
1259
+ if (iqs > 0) {
1260
+ return;
1261
+ }
1262
+
1263
+ reinterpret_cast<sycl::half &>(y[ib].ds.x()) = d;
1264
+ reinterpret_cast<sycl::half &>(y[ib].ds.y()) = sum;
1265
+ }
1266
+
1267
+ template<int qk, int qr, dequantize_kernel_t dequantize_kernel, typename dst_t>
1268
+ static void k_get_rows(
1269
+ const void * src0, const int32_t * src1, dst_t * dst,
1270
+ int64_t ne00, /*int64_t ne01, int64_t ne02, int64_t ne03,*/
1271
+ /*int64_t ne10, int64_t ne11,*/ int64_t ne12, /*int64_t ne13,*/
1272
+ /*size_t s0,*/ size_t s1, size_t s2, size_t s3,
1273
+ /*size_t nb00,*/ size_t nb01, size_t nb02, size_t nb03,
1274
+ size_t s10, size_t s11, size_t s12,
1275
+ const sycl::nd_item<3> &item_ct1/*, size_t s13*/) {
1276
+
1277
+ const int i00 = (item_ct1.get_group(2) * item_ct1.get_local_range(2) +
1278
+ item_ct1.get_local_id(2)) *
1279
+ 2;
1280
+ const int i10 = item_ct1.get_local_range(1) * item_ct1.get_group(1) +
1281
+ item_ct1.get_local_id(1);
1282
+ const int i11 = (item_ct1.get_group(0) * item_ct1.get_local_range(0) +
1283
+ item_ct1.get_local_id(0)) /
1284
+ ne12;
1285
+ const int i12 = (item_ct1.get_group(0) * item_ct1.get_local_range(0) +
1286
+ item_ct1.get_local_id(0)) %
1287
+ ne12;
1288
+
1289
+ if (i00 >= ne00) {
1290
+ return;
1291
+ }
1292
+
1293
+ const int i01 = src1[i10*s10 + i11*s11 + i12*s12];
1294
+
1295
+ dst_t * dst_row = dst + i10*s1 + i11*s2 + i12*s3;
1296
+ const void * src0_row = (const char *)src0 + i01*nb01 + i11*nb02 + i12*nb03;
1297
+
1298
+ const int ib = i00/qk; // block index
1299
+ const int iqs = (i00%qk)/qr; // quant index
1300
+ const int iybs = i00 - i00%qk; // dst block start index
1301
+ const int y_offset = qr == 1 ? 1 : qk/2;
1302
+
1303
+ // dequantize
1304
+ dfloat2 v;
1305
+ dequantize_kernel(src0_row, ib, iqs, v);
1306
+
1307
+ dst_row[iybs + iqs + 0] = v.x();
1308
+ dst_row[iybs + iqs + y_offset] = v.y();
1309
+ }
1310
+
1311
+ template<typename src0_t, typename dst_t>
1312
+ static void k_get_rows_float(
1313
+ const src0_t * src0, const int32_t * src1, dst_t * dst,
1314
+ int64_t ne00, /*int64_t ne01, int64_t ne02, int64_t ne03,*/
1315
+ /*int64_t ne10, int64_t ne11,*/ int64_t ne12, /*int64_t ne13,*/
1316
+ /*size_t s0,*/ size_t s1, size_t s2, size_t s3,
1317
+ /*size_t nb00,*/ size_t nb01, size_t nb02, size_t nb03,
1318
+ size_t s10, size_t s11, size_t s12,
1319
+ const sycl::nd_item<3> &item_ct1/*, size_t s13*/) {
1320
+
1321
+ const int i00 = item_ct1.get_group(2) * item_ct1.get_local_range(2) +
1322
+ item_ct1.get_local_id(2);
1323
+ const int i10 = item_ct1.get_local_range(1) * item_ct1.get_group(1) +
1324
+ item_ct1.get_local_id(1);
1325
+ const int i11 = (item_ct1.get_group(0) * item_ct1.get_local_range(0) +
1326
+ item_ct1.get_local_id(0)) /
1327
+ ne12;
1328
+ const int i12 = (item_ct1.get_group(0) * item_ct1.get_local_range(0) +
1329
+ item_ct1.get_local_id(0)) %
1330
+ ne12;
1331
+
1332
+ if (i00 >= ne00) {
1333
+ return;
1334
+ }
1335
+
1336
+ const int i01 = src1[i10*s10 + i11*s11 + i12*s12];
1337
+
1338
+ dst_t * dst_row = dst + i10*s1 + i11*s2 + i12*s3;
1339
+ const src0_t * src0_row = (const src0_t *)((const char *)src0 + i01*nb01 + i11*nb02 + i12*nb03);
1340
+
1341
+ dst_row[i00] = src0_row[i00];
1342
+ }
1343
+
1344
+ static void mul_mat_p021_f16_f32(
1345
+ const void * __restrict__ vx, const float * __restrict__ y, float * __restrict__ dst,
1346
+ const int ncols_x, const int nrows_x, const int nchannels_x, const int nchannels_y,
1347
+ const sycl::nd_item<3> &item_ct1) {
1348
+
1349
+ const sycl::half *x = (const sycl::half *)vx;
1350
+
1351
+ const int row_x = item_ct1.get_local_range(1) * item_ct1.get_group(1) +
1352
+ item_ct1.get_local_id(1);
1353
+ const int channel = item_ct1.get_local_range(0) * item_ct1.get_group(0) +
1354
+ item_ct1.get_local_id(0);
1355
+ const int channel_x = channel / (nchannels_y / nchannels_x);
1356
+
1357
+ const int nrows_y = ncols_x;
1358
+ const int nrows_dst = nrows_x;
1359
+ const int row_dst = row_x;
1360
+
1361
+ float tmp = 0.0f;
1362
+
1363
+ for (int col_x0 = 0; col_x0 < ncols_x;
1364
+ col_x0 += item_ct1.get_local_range(2)) {
1365
+ const int col_x = col_x0 + item_ct1.get_local_id(2);
1366
+
1367
+ if (col_x >= ncols_x) {
1368
+ break;
1369
+ }
1370
+
1371
+ // x is transposed and permuted
1372
+ const int ix = row_x*nchannels_x*ncols_x + channel_x*ncols_x + col_x;
1373
+ const float xi =
1374
+ sycl::vec<sycl::half, 1>(x[ix])
1375
+ .convert<float, sycl::rounding_mode::automatic>()[0];
1376
+
1377
+ const int row_y = col_x;
1378
+
1379
+
1380
+ // y is not transposed but permuted
1381
+ const int iy = channel*nrows_y + row_y;
1382
+
1383
+ tmp += xi * y[iy];
1384
+ }
1385
+
1386
+ // dst is not transposed and not permuted
1387
+ const int idst = channel*nrows_dst + row_dst;
1388
+
1389
+ // sum up partial sums and write back result
1390
+ #pragma unroll
1391
+ for (int mask = WARP_SIZE / 2; mask > 0; mask >>= 1) {
1392
+ tmp +=
1393
+ dpct::permute_sub_group_by_xor(item_ct1.get_sub_group(), tmp, mask);
1394
+ }
1395
+
1396
+ if (item_ct1.get_local_id(2) == 0) {
1397
+ dst[idst] = tmp;
1398
+ }
1399
+ }
1400
+
1401
+ static void mul_mat_vec_nc_f16_f32( // nc == non-contiguous
1402
+ const void * __restrict__ vx, const float * __restrict__ y, float * __restrict__ dst, const int ncols_x, const int nrows_x,
1403
+ const int row_stride_x, const int channel_stride_x, const int channel_x_divisor,
1404
+ const sycl::nd_item<3> &item_ct1) {
1405
+
1406
+ const sycl::half *x = (const sycl::half *)vx;
1407
+
1408
+ const int row_x = item_ct1.get_local_range(1) * item_ct1.get_group(1) +
1409
+ item_ct1.get_local_id(1);
1410
+ const int channel = item_ct1.get_local_range(0) * item_ct1.get_group(0) +
1411
+ item_ct1.get_local_id(0);
1412
+ const int channel_x = channel / channel_x_divisor;
1413
+
1414
+ const int nrows_y = ncols_x;
1415
+ const int nrows_dst = nrows_x;
1416
+ const int row_dst = row_x;
1417
+
1418
+ const int idst = channel*nrows_dst + row_dst;
1419
+
1420
+ float tmp = 0.0f;
1421
+
1422
+ for (int col_x0 = 0; col_x0 < ncols_x;
1423
+ col_x0 += item_ct1.get_local_range(2)) {
1424
+ const int col_x = col_x0 + item_ct1.get_local_id(2);
1425
+
1426
+ if (col_x >= ncols_x) {
1427
+ break;
1428
+ }
1429
+
1430
+ const int row_y = col_x;
1431
+
1432
+ const int ix = channel_x*channel_stride_x + row_x*row_stride_x + col_x;
1433
+ const int iy = channel*nrows_y + row_y;
1434
+
1435
+ const float xi =
1436
+ sycl::vec<sycl::half, 1>(x[ix])
1437
+ .convert<float, sycl::rounding_mode::automatic>()[0];
1438
+
1439
+ tmp += xi * y[iy];
1440
+ }
1441
+
1442
+ // sum up partial sums and write back result
1443
+ #pragma unroll
1444
+ for (int mask = WARP_SIZE / 2; mask > 0; mask >>= 1) {
1445
+ tmp +=
1446
+ dpct::permute_sub_group_by_xor(item_ct1.get_sub_group(), tmp, mask);
1447
+ }
1448
+
1449
+ if (item_ct1.get_local_id(2) == 0) {
1450
+ dst[idst] = tmp;
1451
+ }
1452
+ }
1453
+
1454
+ static void cpy_1_f32_f32(const char * cxi, char * cdsti) {
1455
+ const float * xi = (const float *) cxi;
1456
+ float * dsti = (float *) cdsti;
1457
+
1458
+ *dsti = *xi;
1459
+ }
1460
+
1461
+ static void cpy_1_f32_f16(const char * cxi, char * cdsti) {
1462
+ const float * xi = (const float *) cxi;
1463
+ sycl::half *dsti = (sycl::half *)cdsti;
1464
+
1465
+ *dsti = sycl::vec<float, 1>(*xi)
1466
+ .convert<sycl::half, sycl::rounding_mode::automatic>()[0];
1467
+ }
1468
+
1469
+ static void cpy_1_f16_f16(const char * cxi, char * cdsti) {
1470
+ const sycl::half *xi = (const sycl::half *)cxi;
1471
+ sycl::half *dsti = (sycl::half *)cdsti;
1472
+
1473
+ *dsti = *xi;
1474
+ }
1475
+
1476
+ static void cpy_1_f16_f32(const char * cxi, char * cdsti) {
1477
+ const sycl::half *xi = (const sycl::half *)cxi;
1478
+ float * dsti = (float *) cdsti;
1479
+
1480
+ *dsti = *xi;
1481
+ }
1482
+
1483
+ static void cpy_1_i16_i16(const char * cxi, char * cdsti) {
1484
+ const int16_t *xi = (const int16_t *)cxi;
1485
+ int16_t *dsti = (int16_t *)cdsti;
1486
+
1487
+ *dsti = *xi;
1488
+ }
1489
+
1490
+ static void cpy_1_i32_i32(const char * cxi, char * cdsti) {
1491
+ const int32_t *xi = (const int32_t *)cxi;
1492
+ int32_t *dsti = (int32_t *)cdsti;
1493
+
1494
+ *dsti = *xi;
1495
+ }
1496
+
1497
+ template <cpy_kernel_t cpy_1>
1498
+ static void cpy_f32_f16(const char * cx, char * cdst, const int ne,
1499
+ const int ne00, const int ne01, const int ne02, const int nb00, const int nb01, const int nb02,
1500
+ const int nb03, const int ne10, const int ne11, const int ne12, const int nb10, const int nb11,
1501
+ const int nb12, const int nb13, const sycl::nd_item<3> &item_ct1) {
1502
+ const int i = item_ct1.get_local_range(2) * item_ct1.get_group(2) +
1503
+ item_ct1.get_local_id(2);
1504
+
1505
+ if (i >= ne) {
1506
+ return;
1507
+ }
1508
+
1509
+ // determine indices i02/i12, i01/i11, i00/i10 as a function of index i of flattened tensor
1510
+ // then combine those indices with the corresponding byte offsets to get the total offsets
1511
+ const int i03 = i/(ne00 * ne01 * ne02);
1512
+ const int i02 = (i - i03*ne00*ne01*ne02 )/ (ne00*ne01);
1513
+ const int i01 = (i - i03*ne00*ne01*ne02 - i02*ne01*ne00) / ne00;
1514
+ const int i00 = i - i03*ne00*ne01*ne02 - i02*ne01*ne00 - i01*ne00;
1515
+ const int x_offset = i00*nb00 + i01*nb01 + i02*nb02 + i03 * nb03;
1516
+
1517
+ const int i13 = i/(ne10 * ne11 * ne12);
1518
+ const int i12 = (i - i13*ne10*ne11*ne12) / (ne10*ne11);
1519
+ const int i11 = (i - i13*ne10*ne11*ne12 - i12*ne10*ne11) / ne10;
1520
+ const int i10 = i - i13*ne10*ne11*ne12 - i12*ne10*ne11 - i11*ne10;
1521
+ const int dst_offset = i10*nb10 + i11*nb11 + i12*nb12 + i13 * nb13;
1522
+
1523
+ cpy_1(cx + x_offset, cdst + dst_offset);
1524
+ }
1525
+
1526
+ static void cpy_blck_f32_q8_0(const char * cxi, char * cdsti) {
1527
+ const float * xi = (const float *) cxi;
1528
+ block_q8_0 * dsti = (block_q8_0 *) cdsti;
1529
+
1530
+ float amax = 0.0f; // absolute max
1531
+
1532
+ for (int j = 0; j < QK8_0; j++) {
1533
+ const float v = xi[j];
1534
+ amax = sycl::fmax(amax, sycl::fabs((float)v));
1535
+ }
1536
+
1537
+ const float d = amax / ((1 << 7) - 1);
1538
+ const float id = d ? 1.0f/d : 0.0f;
1539
+
1540
+ dsti->d = d;
1541
+
1542
+ for (int j = 0; j < QK8_0; ++j) {
1543
+ const float x0 = xi[j]*id;
1544
+
1545
+ dsti->qs[j] = sycl::round((float)x0);
1546
+ }
1547
+ }
1548
+
1549
+ static void cpy_blck_f32_q4_0(const char * cxi, char * cdsti) {
1550
+ const float * xi = (const float *) cxi;
1551
+ block_q4_0 * dsti = (block_q4_0 *) cdsti;
1552
+
1553
+ float amax = 0.0f;
1554
+ float vmax = 0.0f;
1555
+
1556
+ for (int j = 0; j < QK4_0; ++j) {
1557
+ const float v = xi[j];
1558
+ if (amax < sycl::fabs((float)v)) {
1559
+ amax = sycl::fabs((float)v);
1560
+ vmax = v;
1561
+ }
1562
+ }
1563
+
1564
+ const float d = vmax / -8;
1565
+ const float id = d ? 1.0f/d : 0.0f;
1566
+
1567
+ dsti->d = d;
1568
+
1569
+ for (int j = 0; j < QK4_0/2; ++j) {
1570
+ const float x0 = xi[0 + j]*id;
1571
+ const float x1 = xi[QK4_0/2 + j]*id;
1572
+
1573
+ const uint8_t xi0 = dpct::min(15, (int8_t)(x0 + 8.5f));
1574
+ const uint8_t xi1 = dpct::min(15, (int8_t)(x1 + 8.5f));
1575
+
1576
+ dsti->qs[j] = xi0;
1577
+ dsti->qs[j] |= xi1 << 4;
1578
+ }
1579
+ }
1580
+
1581
+ static void cpy_blck_f32_q4_1(const char * cxi, char * cdsti) {
1582
+ const float * xi = (const float *) cxi;
1583
+ block_q4_1 * dsti = (block_q4_1 *) cdsti;
1584
+
1585
+ float vmin = FLT_MAX;
1586
+ float vmax = -FLT_MAX;
1587
+
1588
+ for (int j = 0; j < QK4_1; ++j) {
1589
+ const float v = xi[j];
1590
+
1591
+ if (v < vmin) vmin = v;
1592
+ if (v > vmax) vmax = v;
1593
+ }
1594
+
1595
+ const float d = (vmax - vmin) / ((1 << 4) - 1);
1596
+ const float id = d ? 1.0f/d : 0.0f;
1597
+
1598
+ dsti->dm.x() = d;
1599
+ dsti->dm.y() = vmin;
1600
+
1601
+ for (int j = 0; j < QK4_1/2; ++j) {
1602
+ const float x0 = (xi[0 + j] - vmin)*id;
1603
+ const float x1 = (xi[QK4_1/2 + j] - vmin)*id;
1604
+
1605
+ const uint8_t xi0 = dpct::min(15, (int8_t)(x0 + 0.5f));
1606
+ const uint8_t xi1 = dpct::min(15, (int8_t)(x1 + 0.5f));
1607
+
1608
+ dsti->qs[j] = xi0;
1609
+ dsti->qs[j] |= xi1 << 4;
1610
+ }
1611
+ }
1612
+
1613
+ template <cpy_kernel_t cpy_blck, int qk>
1614
+ static void cpy_f32_q(const char * cx, char * cdst, const int ne,
1615
+ const int ne00, const int ne01, const int ne02, const int nb00, const int nb01, const int nb02,
1616
+ const int nb03, const int ne10, const int ne11, const int ne12, const int nb10, const int nb11,
1617
+ const int nb12, const int nb13, const sycl::nd_item<3> &item_ct1) {
1618
+ const int i = (item_ct1.get_local_range(2) * item_ct1.get_group(2) +
1619
+ item_ct1.get_local_id(2)) *
1620
+ qk;
1621
+
1622
+ if (i >= ne) {
1623
+ return;
1624
+ }
1625
+
1626
+ const int i03 = i/(ne00 * ne01 * ne02);
1627
+ const int i02 = (i - i03*ne00*ne01*ne02 )/ (ne00*ne01);
1628
+ const int i01 = (i - i03*ne00*ne01*ne02 - i02*ne01*ne00) / ne00;
1629
+ const int i00 = i - i03*ne00*ne01*ne02 - i02*ne01*ne00 - i01*ne00;
1630
+ const int x_offset = i00*nb00 + i01*nb01 + i02*nb02 + i03 * nb03;
1631
+
1632
+ const int i13 = i/(ne10 * ne11 * ne12);
1633
+ const int i12 = (i - i13*ne10*ne11*ne12) / (ne10*ne11);
1634
+ const int i11 = (i - i13*ne10*ne11*ne12 - i12*ne10*ne11) / ne10;
1635
+ const int i10 = i - i13*ne10*ne11*ne12 - i12*ne10*ne11 - i11*ne10;
1636
+ const int dst_offset = (i10/qk)*nb10 + i11*nb11 + i12*nb12 + i13*nb13;
1637
+
1638
+ cpy_blck(cx + x_offset, cdst + dst_offset);
1639
+ }
1640
+
1641
+ static void k_sum_rows_f32(const float * x, float * dst, const int ncols,
1642
+ const sycl::nd_item<3> &item_ct1) {
1643
+ const int row = item_ct1.get_group(1);
1644
+ const int col = item_ct1.get_local_id(2);
1645
+
1646
+ float sum = 0.0f;
1647
+ for (int i = col; i < ncols; i += item_ct1.get_local_range(2)) {
1648
+ sum += x[row * ncols + i];
1649
+ }
1650
+
1651
+ sum = warp_reduce_sum(sum, item_ct1);
1652
+
1653
+ if (col == 0) {
1654
+ dst[row] = sum;
1655
+ }
1656
+ }
1657
+
1658
+
1659
+ template<typename T>
1660
+ static inline void ggml_sycl_swap(T & a, T & b) {
1661
+ T tmp = a;
1662
+ a = b;
1663
+ b = tmp;
1664
+ }
1665
+
1666
+ template <ggml_sort_order order>
1667
+ __dpct_inline__ static void
1668
+ k_argsort_f32_i32(const float *x, int *dst, const int ncols, int ncols_pad,
1669
+ const sycl::nd_item<3> &item_ct1, uint8_t *dpct_local) {
1670
+ // bitonic sort
1671
+ int col = item_ct1.get_local_id(2);
1672
+ int row = item_ct1.get_group(1);
1673
+
1674
+ if (col >= ncols_pad) {
1675
+ return;
1676
+ }
1677
+
1678
+ const float * x_row = x + row * ncols;
1679
+ auto dst_row = (int *)dpct_local;
1680
+
1681
+ // initialize indices
1682
+ dst_row[col] = col;
1683
+
1684
+ item_ct1.barrier(sycl::access::fence_space::local_space);
1685
+
1686
+ for (int k = 2; k <= ncols_pad; k *= 2) {
1687
+ for (int j = k / 2; j > 0; j /= 2) {
1688
+ int ixj = col ^ j;
1689
+ if (ixj > col) {
1690
+ if ((col & k) == 0) {
1691
+ if (dst_row[col] >= ncols ||
1692
+ (dst_row[ixj] < ncols && (order == GGML_SORT_ORDER_ASC ?
1693
+ x_row[dst_row[col]] > x_row[dst_row[ixj]] :
1694
+ x_row[dst_row[col]] < x_row[dst_row[ixj]]))
1695
+ ) {
1696
+ ggml_sycl_swap(dst_row[col], dst_row[ixj]);
1697
+ }
1698
+ } else {
1699
+ if (dst_row[ixj] >= ncols ||
1700
+ (dst_row[col] < ncols && (order == GGML_SORT_ORDER_ASC ?
1701
+ x_row[dst_row[col]] < x_row[dst_row[ixj]] :
1702
+ x_row[dst_row[col]] > x_row[dst_row[ixj]]))
1703
+ ) {
1704
+ ggml_sycl_swap(dst_row[col], dst_row[ixj]);
1705
+ }
1706
+ }
1707
+ }
1708
+ /*
1709
+ DPCT1118:1: SYCL group functions and algorithms must be encountered
1710
+ in converged control flow. You may need to adjust the code.
1711
+ */
1712
+ item_ct1.barrier(sycl::access::fence_space::local_space);
1713
+ }
1714
+ }
1715
+
1716
+ // copy the result to dst without the padding
1717
+ if (col < ncols) {
1718
+ dst[row * ncols + col] = dst_row[col];
1719
+ }
1720
+ }
1721
+
1722
+
1723
+ static void diag_mask_inf_f32(const float * x, float * dst, const int ncols, const int rows_per_channel, const int n_past,
1724
+ const sycl::nd_item<3> &item_ct1) {
1725
+ const int col = item_ct1.get_local_range(1) * item_ct1.get_group(1) +
1726
+ item_ct1.get_local_id(1);
1727
+ const int row = item_ct1.get_local_range(2) * item_ct1.get_group(2) +
1728
+ item_ct1.get_local_id(2);
1729
+
1730
+ if (col >= ncols) {
1731
+ return;
1732
+ }
1733
+
1734
+ const int i = row*ncols + col;
1735
+ //dst[i] = col > (n_past + row % rows_per_channel) ? -INFINITY : x[i];
1736
+ //dst[i] = x[i] - (col > n_past + row % rows_per_channel) * INT_MAX; // equivalent within rounding error but slightly faster on GPU
1737
+ dst[i] = x[i] - (col > n_past + row % rows_per_channel) * FLT_MAX;
1738
+ }
1739
+
1740
+ static void scale_f32(const float * x, float * dst, const float scale, const int k,
1741
+ const sycl::nd_item<3> &item_ct1) {
1742
+ const int i = item_ct1.get_local_range(2) * item_ct1.get_group(2) +
1743
+ item_ct1.get_local_id(2);
1744
+
1745
+ if (i >= k) {
1746
+ return;
1747
+ }
1748
+
1749
+ dst[i] = scale * x[i];
1750
+ }
1751
+
1752
+ static void clamp_f32(const float * x, float * dst, const float min, const float max, const int k,
1753
+ const sycl::nd_item<3> &item_ct1) {
1754
+ const int i = item_ct1.get_local_range(2) * item_ct1.get_group(2) +
1755
+ item_ct1.get_local_id(2);
1756
+
1757
+ if (i >= k) {
1758
+ return;
1759
+ }
1760
+
1761
+ dst[i] = x[i] < min ? min : (x[i] > max ? max : x[i]);
1762
+ }
1763
+
1764
+ template <typename Ti, typename To>
1765
+ static void pool2d_nchw_kernel(
1766
+ const int ih, const int iw, const int oh, const int ow,
1767
+ const int kh, const int kw, const int sh, const int sw,
1768
+ const int ph, const int pw, const int parallel_elements,
1769
+ const Ti* src, To* dst, const enum ggml_op_pool op,
1770
+ const sycl::nd_item<3> &item_ct1) {
1771
+ int idx = item_ct1.get_local_id(2) +
1772
+ item_ct1.get_group(2) * item_ct1.get_local_range(2);
1773
+ if (idx >= parallel_elements) {
1774
+ return;
1775
+ }
1776
+
1777
+ const int I_HW = ih * iw;
1778
+ const int O_HW = oh * ow;
1779
+ const int nc = idx / O_HW;
1780
+ const int cur_oh = idx % O_HW / ow;
1781
+ const int cur_ow = idx % O_HW % ow;
1782
+ const Ti* i_ptr = src + nc * I_HW;
1783
+ To* o_ptr = dst + nc * O_HW;
1784
+ const int start_h = cur_oh * sh - ph;
1785
+ const int bh = sycl::max(0, start_h);
1786
+ const int eh = sycl::min(ih, start_h + kh);
1787
+ const int start_w = cur_ow * sw - pw;
1788
+ const int bw = sycl::max(0, start_w);
1789
+ const int ew = sycl::min(iw, start_w + kw);
1790
+
1791
+ To res = 0;
1792
+
1793
+ switch (op) {
1794
+ case GGML_OP_POOL_AVG: res = 0; break;
1795
+ case GGML_OP_POOL_MAX: res = -FLT_MAX; break;
1796
+ default:
1797
+ res = (To) sycl::nan(uint32_t(0));
1798
+ break;
1799
+ }
1800
+
1801
+ for (int i = bh; i < eh; i += 1) {
1802
+ for (int j = bw; j < ew; j += 1) {
1803
+ #if DPCT_COMPATIBILITY_TEMP >= 350
1804
+ /*
1805
+ DPCT1098:106: The '*' expression is used instead of the __ldg
1806
+ call. These two expressions do not provide the exact same
1807
+ functionality. Check the generated code for potential precision
1808
+ and/or performance issues.
1809
+ */
1810
+ Ti cur = *(i_ptr + i * iw + j);
1811
+ #else
1812
+ Ti cur = i_ptr[i * iw + j];
1813
+ #endif
1814
+ switch (op) {
1815
+ case GGML_OP_POOL_AVG: res += (cur / (kh * kw)); break;
1816
+ case GGML_OP_POOL_MAX: res = sycl::max(res, (To)cur); break;
1817
+ default:
1818
+ res = (To) sycl::nan(uint32_t(0));
1819
+ break;
1820
+ }
1821
+ }
1822
+ }
1823
+ o_ptr[cur_oh * ow + cur_ow] = res;
1824
+ }
1825
+
1826
+ template <int qk, int qr, dequantize_kernel_t dq>
1827
+ static void get_rows_sycl(ggml_backend_sycl_context & ctx, const ggml_tensor *src0, const ggml_tensor *src1,
1828
+ ggml_tensor *dst, const void *src0_dd,
1829
+ const int32_t *src1_dd, float *dst_dd,
1830
+ queue_ptr stream) {
1831
+
1832
+ GGML_TENSOR_BINARY_OP_LOCALS
1833
+
1834
+ const sycl::range<3> block_dims(1, 1, SYCL_GET_ROWS_BLOCK_SIZE);
1835
+ const int block_num_x = (ne00 + 2*SYCL_GET_ROWS_BLOCK_SIZE - 1) / (2*SYCL_GET_ROWS_BLOCK_SIZE);
1836
+ const sycl::range<3> block_nums(ne11 * ne12, ne10, block_num_x);
1837
+
1838
+ // strides in elements
1839
+ //const size_t s0 = nb0 / ggml_element_size(dst);
1840
+ const size_t s1 = nb1 / ggml_element_size(dst);
1841
+ const size_t s2 = nb2 / ggml_element_size(dst);
1842
+ const size_t s3 = nb3 / ggml_element_size(dst);
1843
+
1844
+ const size_t s10 = nb10 / ggml_element_size(src1);
1845
+ const size_t s11 = nb11 / ggml_element_size(src1);
1846
+ const size_t s12 = nb12 / ggml_element_size(src1);
1847
+ //const size_t s13 = nb13 / ggml_element_size(src1);
1848
+
1849
+ GGML_ASSERT(ne00 % 2 == 0);
1850
+
1851
+ stream->parallel_for(sycl::nd_range<3>(block_nums * block_dims, block_dims),
1852
+ [=](sycl::nd_item<3> item_ct1) {
1853
+ k_get_rows<qk, qr, dq>(
1854
+ src0_dd, src1_dd, dst_dd, ne00, ne12, s1, s2,
1855
+ s3, nb01, nb02, nb03, s10, s11, s12, item_ct1);
1856
+ });
1857
+
1858
+ GGML_UNUSED(dst);
1859
+ GGML_UNUSED(ctx);
1860
+ }
1861
+
1862
+ template <typename src0_t>
1863
+ static void get_rows_sycl_float(ggml_backend_sycl_context & ctx, const ggml_tensor *src0,
1864
+ const ggml_tensor *src1, ggml_tensor *dst,
1865
+ const src0_t *src0_dd, const int32_t *src1_dd,
1866
+ float *dst_dd, queue_ptr stream) {
1867
+
1868
+ GGML_TENSOR_BINARY_OP_LOCALS
1869
+
1870
+ const sycl::range<3> block_dims(1, 1, SYCL_GET_ROWS_BLOCK_SIZE);
1871
+ const int block_num_x = (ne00 + SYCL_GET_ROWS_BLOCK_SIZE - 1) / SYCL_GET_ROWS_BLOCK_SIZE;
1872
+ const sycl::range<3> block_nums(ne11 * ne12, ne10, block_num_x);
1873
+
1874
+ // strides in elements
1875
+ //const size_t s0 = nb0 / ggml_element_size(dst);
1876
+ const size_t s1 = nb1 / ggml_element_size(dst);
1877
+ const size_t s2 = nb2 / ggml_element_size(dst);
1878
+ const size_t s3 = nb3 / ggml_element_size(dst);
1879
+
1880
+ const size_t s10 = nb10 / ggml_element_size(src1);
1881
+ const size_t s11 = nb11 / ggml_element_size(src1);
1882
+ const size_t s12 = nb12 / ggml_element_size(src1);
1883
+ //const size_t s13 = nb13 / ggml_element_size(src1);
1884
+
1885
+ {
1886
+ dpct::has_capability_or_fail(stream->get_device(),
1887
+ {sycl::aspect::fp16});
1888
+
1889
+ stream->parallel_for(
1890
+ sycl::nd_range<3>(block_nums * block_dims, block_dims),
1891
+ [=](sycl::nd_item<3> item_ct1) {
1892
+ k_get_rows_float(src0_dd, src1_dd, dst_dd, ne00, ne12, s1, s2,
1893
+ s3, nb01, nb02, nb03, s10, s11, s12, item_ct1);
1894
+ });
1895
+ }
1896
+
1897
+ GGML_UNUSED(dst);
1898
+ GGML_UNUSED(ctx);
1899
+ }
1900
+
1901
+ static void quantize_row_q8_1_sycl(const float *x, void *vy, const int kx,
1902
+ const int ky, const int kx_padded,
1903
+ queue_ptr stream) {
1904
+ const int block_num_x = (kx_padded + SYCL_QUANTIZE_BLOCK_SIZE - 1) / SYCL_QUANTIZE_BLOCK_SIZE;
1905
+ const sycl::range<3> num_blocks(1, ky, block_num_x);
1906
+ int constexpr QUANT_BLOCK_TILE = QK8_1 / WARP_SIZE;
1907
+ static_assert(QK8_1 % WARP_SIZE == 0);
1908
+ const sycl::range<3> block_size(1, 1, SYCL_QUANTIZE_BLOCK_SIZE / QUANT_BLOCK_TILE);
1909
+ {
1910
+ dpct::has_capability_or_fail(stream->get_device(),
1911
+ {sycl::aspect::fp16});
1912
+
1913
+ stream->parallel_for(
1914
+ sycl::nd_range<3>(num_blocks * block_size, block_size),
1915
+ [=](sycl::nd_item<3> item_ct1) [[intel::reqd_sub_group_size(WARP_SIZE)]] {
1916
+ quantize_q8_1<QUANT_BLOCK_TILE>(x, vy, kx, kx_padded, item_ct1);
1917
+ });
1918
+ }
1919
+ }
1920
+
1921
+ static void ggml_mul_mat_p021_f16_f32_sycl(const void *vx, const float *y,
1922
+ float *dst, const int ncols_x,
1923
+ const int nrows_x,
1924
+ const int nchannels_x,
1925
+ const int nchannels_y,
1926
+ queue_ptr stream) {
1927
+
1928
+ const sycl::range<3> block_nums(nchannels_y, nrows_x, 1);
1929
+ const sycl::range<3> block_dims(1, 1, WARP_SIZE);
1930
+ {
1931
+ dpct::has_capability_or_fail(stream->get_device(),
1932
+ {sycl::aspect::fp16});
1933
+
1934
+ stream->parallel_for(
1935
+ sycl::nd_range<3>(block_nums * block_dims, block_dims),
1936
+ [=](sycl::nd_item<3> item_ct1) [[intel::reqd_sub_group_size(WARP_SIZE)]] {
1937
+ mul_mat_p021_f16_f32(vx, y, dst, ncols_x, nrows_x, nchannels_x,
1938
+ nchannels_y, item_ct1);
1939
+ });
1940
+ }
1941
+ }
1942
+
1943
+ static void ggml_mul_mat_vec_nc_f16_f32_sycl(
1944
+ const void *vx, const float *y, float *dst, const int ncols_x,
1945
+ const int nrows_x, const int row_stride_x, const int nchannels_x,
1946
+ const int nchannels_y, const int channel_stride_x, queue_ptr stream) {
1947
+
1948
+ const sycl::range<3> block_nums(nchannels_y, nrows_x, 1);
1949
+ const sycl::range<3> block_dims(1, 1, WARP_SIZE);
1950
+ {
1951
+ dpct::has_capability_or_fail(stream->get_device(),
1952
+ {sycl::aspect::fp16});
1953
+
1954
+ stream->parallel_for(
1955
+ sycl::nd_range<3>(block_nums * block_dims, block_dims),
1956
+ [=](sycl::nd_item<3> item_ct1) [[intel::reqd_sub_group_size(WARP_SIZE)]] {
1957
+ mul_mat_vec_nc_f16_f32(vx, y, dst, ncols_x, nrows_x,
1958
+ row_stride_x, channel_stride_x,
1959
+ nchannels_y / nchannels_x, item_ct1);
1960
+ });
1961
+ }
1962
+ }
1963
+
1964
+ static void
1965
+ ggml_cpy_f16_f32_sycl(const char *cx, char *cdst, const int ne, const int ne00,
1966
+ const int ne01, const int ne02, const int nb00,
1967
+ const int nb01, const int nb02, const int nb03,
1968
+ const int ne10, const int ne11, const int ne12,
1969
+ const int nb10, const int nb11, const int nb12,
1970
+ const int nb13, queue_ptr stream) {
1971
+
1972
+ const int num_blocks = (ne + SYCL_CPY_BLOCK_SIZE - 1) / SYCL_CPY_BLOCK_SIZE;
1973
+ {
1974
+ dpct::has_capability_or_fail(stream->get_device(),
1975
+ {sycl::aspect::fp16});
1976
+
1977
+ stream->parallel_for(
1978
+ sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks) *
1979
+ sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE),
1980
+ sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE)),
1981
+ [=](sycl::nd_item<3> item_ct1) {
1982
+ cpy_f32_f16<cpy_1_f16_f32>(cx, cdst, ne, ne00, ne01, ne02, nb00,
1983
+ nb01, nb02, nb03, ne10, ne11, ne12,
1984
+ nb10, nb11, nb12, nb13, item_ct1);
1985
+ });
1986
+ }
1987
+ }
1988
+
1989
+ static void ggml_cpy_f32_f32_sycl(const char *cx, char *cdst, const int ne,
1990
+ const int ne00, const int ne01,
1991
+ const int ne02, const int nb00,
1992
+ const int nb01, const int nb02,
1993
+ const int nb03, const int ne10,
1994
+ const int ne11, const int ne12,
1995
+ const int nb10, const int nb11,
1996
+ const int nb12, const int nb13,
1997
+ queue_ptr stream) {
1998
+
1999
+ const int num_blocks = (ne + SYCL_CPY_BLOCK_SIZE - 1) / SYCL_CPY_BLOCK_SIZE;
2000
+ {
2001
+ dpct::has_capability_or_fail(stream->get_device(),
2002
+ {sycl::aspect::fp16});
2003
+
2004
+ stream->parallel_for(
2005
+ sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks) *
2006
+ sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE),
2007
+ sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE)),
2008
+ [=](sycl::nd_item<3> item_ct1) {
2009
+ cpy_f32_f16<cpy_1_f32_f32>(cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02,
2010
+ nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13,
2011
+ item_ct1);
2012
+ });
2013
+ }
2014
+ }
2015
+
2016
+ static void ggml_cpy_f32_f16_sycl(const char *cx, char *cdst, const int ne,
2017
+ const int ne00, const int ne01,
2018
+ const int ne02, const int nb00,
2019
+ const int nb01, const int nb02,
2020
+ const int nb03, const int ne10,
2021
+ const int ne11, const int ne12,
2022
+ const int nb10, const int nb11,
2023
+ const int nb12, const int nb13,
2024
+ queue_ptr stream) {
2025
+
2026
+ const int num_blocks = (ne + SYCL_CPY_BLOCK_SIZE - 1) / SYCL_CPY_BLOCK_SIZE;
2027
+ {
2028
+ dpct::has_capability_or_fail(stream->get_device(),
2029
+ {sycl::aspect::fp16});
2030
+
2031
+ stream->parallel_for(
2032
+ sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks) *
2033
+ sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE),
2034
+ sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE)),
2035
+ [=](sycl::nd_item<3> item_ct1) {
2036
+ cpy_f32_f16<cpy_1_f32_f16>(cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02,
2037
+ nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13,
2038
+ item_ct1);
2039
+ });
2040
+ }
2041
+ }
2042
+
2043
+ static void ggml_cpy_f32_q8_0_sycl(const char *cx, char *cdst, const int ne,
2044
+ const int ne00, const int ne01,
2045
+ const int ne02, const int nb00,
2046
+ const int nb01, const int nb02,
2047
+ const int nb03, const int ne10,
2048
+ const int ne11, const int ne12,
2049
+ const int nb10, const int nb11,
2050
+ const int nb12, const int nb13,
2051
+ queue_ptr stream) {
2052
+
2053
+ GGML_ASSERT(ne % QK8_0 == 0);
2054
+ const int num_blocks = ne / QK8_0;
2055
+ stream->parallel_for(sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks),
2056
+ sycl::range<3>(1, 1, 1)),
2057
+ [=](sycl::nd_item<3> item_ct1) {
2058
+ cpy_f32_q<cpy_blck_f32_q8_0, QK8_0>(
2059
+ cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02,
2060
+ nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13,
2061
+ item_ct1);
2062
+ });
2063
+ }
2064
+
2065
+ static void ggml_cpy_f32_q4_0_sycl(const char *cx, char *cdst, const int ne,
2066
+ const int ne00, const int ne01,
2067
+ const int ne02, const int nb00,
2068
+ const int nb01, const int nb02,
2069
+ const int nb03, const int ne10,
2070
+ const int ne11, const int ne12,
2071
+ const int nb10, const int nb11,
2072
+ const int nb12, const int nb13,
2073
+ queue_ptr stream) {
2074
+
2075
+ GGML_ASSERT(ne % QK4_0 == 0);
2076
+ const int num_blocks = ne / QK4_0;
2077
+ stream->parallel_for(sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks),
2078
+ sycl::range<3>(1, 1, 1)),
2079
+ [=](sycl::nd_item<3> item_ct1) {
2080
+ cpy_f32_q<cpy_blck_f32_q4_0, QK4_0>(
2081
+ cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02,
2082
+ nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13,
2083
+ item_ct1);
2084
+ });
2085
+ }
2086
+
2087
+ static void ggml_cpy_f32_q4_1_sycl(const char *cx, char *cdst, const int ne,
2088
+ const int ne00, const int ne01,
2089
+ const int ne02, const int nb00,
2090
+ const int nb01, const int nb02,
2091
+ const int nb03, const int ne10,
2092
+ const int ne11, const int ne12,
2093
+ const int nb10, const int nb11,
2094
+ const int nb12, const int nb13,
2095
+ queue_ptr stream) {
2096
+
2097
+ GGML_ASSERT(ne % QK4_1 == 0);
2098
+ const int num_blocks = ne / QK4_1;
2099
+ stream->parallel_for(sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks),
2100
+ sycl::range<3>(1, 1, 1)),
2101
+ [=](sycl::nd_item<3> item_ct1) {
2102
+ cpy_f32_q<cpy_blck_f32_q4_1, QK4_1>(
2103
+ cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02,
2104
+ nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13,
2105
+ item_ct1);
2106
+ });
2107
+ }
2108
+
2109
+ static void ggml_cpy_f16_f16_sycl(const char *cx, char *cdst, const int ne,
2110
+ const int ne00, const int ne01,
2111
+ const int ne02, const int nb00,
2112
+ const int nb01, const int nb02,
2113
+ const int nb03, const int ne10,
2114
+ const int ne11, const int ne12,
2115
+ const int nb10, const int nb11,
2116
+ const int nb12, const int nb13,
2117
+ queue_ptr stream) {
2118
+
2119
+ const int num_blocks = (ne + SYCL_CPY_BLOCK_SIZE - 1) / SYCL_CPY_BLOCK_SIZE;
2120
+ {
2121
+ dpct::has_capability_or_fail(stream->get_device(),
2122
+ {sycl::aspect::fp16});
2123
+
2124
+ stream->parallel_for(
2125
+ sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks) *
2126
+ sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE),
2127
+ sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE)),
2128
+ [=](sycl::nd_item<3> item_ct1) {
2129
+ cpy_f32_f16<cpy_1_f16_f16>(cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02,
2130
+ nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13,
2131
+ item_ct1);
2132
+ });
2133
+ }
2134
+ }
2135
+
2136
+ static void ggml_cpy_i16_i16_sycl(const char *cx, char *cdst, const int ne,
2137
+ const int ne00, const int ne01,
2138
+ const int ne02, const int nb00,
2139
+ const int nb01, const int nb02,
2140
+ const int nb03, const int ne10,
2141
+ const int ne11, const int ne12,
2142
+ const int nb10, const int nb11,
2143
+ const int nb12, const int nb13,
2144
+ queue_ptr stream) {
2145
+
2146
+ const int num_blocks = (ne + SYCL_CPY_BLOCK_SIZE - 1) / SYCL_CPY_BLOCK_SIZE;
2147
+ {
2148
+ // dpct::has_capability_or_fail(stream->get_device(),
2149
+ // {sycl::aspect::fp16});
2150
+
2151
+ stream->parallel_for(
2152
+ sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks) *
2153
+ sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE),
2154
+ sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE)),
2155
+ [=](sycl::nd_item<3> item_ct1) {
2156
+ cpy_f32_f16<cpy_1_i16_i16>(cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02,
2157
+ nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13,
2158
+ item_ct1);
2159
+ });
2160
+ }
2161
+ }
2162
+
2163
+ static void ggml_cpy_i32_i32_sycl(const char *cx, char *cdst, const int ne,
2164
+ const int ne00, const int ne01,
2165
+ const int ne02, const int nb00,
2166
+ const int nb01, const int nb02,
2167
+ const int nb03, const int ne10,
2168
+ const int ne11, const int ne12,
2169
+ const int nb10, const int nb11,
2170
+ const int nb12, const int nb13,
2171
+ queue_ptr stream) {
2172
+
2173
+ const int num_blocks = (ne + SYCL_CPY_BLOCK_SIZE - 1) / SYCL_CPY_BLOCK_SIZE;
2174
+ {
2175
+ // dpct::has_capability_or_fail(stream->get_device(),
2176
+ // {sycl::aspect::fp16});
2177
+
2178
+ stream->parallel_for(
2179
+ sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks) *
2180
+ sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE),
2181
+ sycl::range<3>(1, 1, SYCL_CPY_BLOCK_SIZE)),
2182
+ [=](sycl::nd_item<3> item_ct1) {
2183
+ cpy_f32_f16<cpy_1_i32_i32>(cx, cdst, ne, ne00, ne01, ne02, nb00, nb01, nb02,
2184
+ nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13,
2185
+ item_ct1);
2186
+ });
2187
+ }
2188
+ }
2189
+
2190
+ static void scale_f32_sycl(const float *x, float *dst, const float scale,
2191
+ const int k, queue_ptr stream) {
2192
+ const int num_blocks = (k + SYCL_SCALE_BLOCK_SIZE - 1) / SYCL_SCALE_BLOCK_SIZE;
2193
+ stream->parallel_for(
2194
+ sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks) *
2195
+ sycl::range<3>(1, 1, SYCL_SCALE_BLOCK_SIZE),
2196
+ sycl::range<3>(1, 1, SYCL_SCALE_BLOCK_SIZE)),
2197
+ [=](sycl::nd_item<3> item_ct1) {
2198
+ scale_f32(x, dst, scale, k, item_ct1);
2199
+ });
2200
+ }
2201
+
2202
+ static void clamp_f32_sycl(const float *x, float *dst, const float min,
2203
+ const float max, const int k,
2204
+ queue_ptr stream) {
2205
+ const int num_blocks = (k + SYCL_CLAMP_BLOCK_SIZE - 1) / SYCL_CLAMP_BLOCK_SIZE;
2206
+ stream->parallel_for(
2207
+ sycl::nd_range<3>(sycl::range<3>(1, 1, num_blocks) *
2208
+ sycl::range<3>(1, 1, SYCL_CLAMP_BLOCK_SIZE),
2209
+ sycl::range<3>(1, 1, SYCL_CLAMP_BLOCK_SIZE)),
2210
+ [=](sycl::nd_item<3> item_ct1) {
2211
+ clamp_f32(x, dst, min, max, k, item_ct1);
2212
+ });
2213
+ }
2214
+
2215
+ static void sum_rows_f32_sycl(const float *x, float *dst, const int ncols,
2216
+ const int nrows, queue_ptr stream) {
2217
+ const sycl::range<3> block_dims(1, 1, WARP_SIZE);
2218
+ const sycl::range<3> block_nums(1, nrows, 1);
2219
+ stream->parallel_for(sycl::nd_range<3>(block_nums * block_dims, block_dims),
2220
+ [=](sycl::nd_item<3> item_ct1)
2221
+ [[intel::reqd_sub_group_size(WARP_SIZE)]] {
2222
+ k_sum_rows_f32(x, dst, ncols, item_ct1);
2223
+ });
2224
+ }
2225
+
2226
+ static int next_power_of_2(int x) {
2227
+ int n = 1;
2228
+ while (n < x) {
2229
+ n *= 2;
2230
+ }
2231
+ return n;
2232
+ }
2233
+
2234
+ static void argsort_f32_i32_sycl(const float *x, int *dst, const int ncols,
2235
+ const int nrows, ggml_sort_order order,
2236
+ queue_ptr stream) {
2237
+ // bitonic sort requires ncols to be power of 2
2238
+ const int ncols_pad = next_power_of_2(ncols);
2239
+
2240
+ const sycl::range<3> block_dims(1, 1, ncols_pad);
2241
+ const sycl::range<3> block_nums(1, nrows, 1);
2242
+ const size_t shared_mem = ncols_pad * sizeof(int);
2243
+
2244
+ if (order == GGML_SORT_ORDER_ASC) {
2245
+ stream->submit([&](sycl::handler &cgh) {
2246
+ sycl::local_accessor<uint8_t, 1> dpct_local_acc_ct1(
2247
+ sycl::range<1>(shared_mem), cgh);
2248
+
2249
+ cgh.parallel_for(
2250
+ sycl::nd_range<3>(block_nums * block_dims, block_dims),
2251
+ [=](sycl::nd_item<3> item_ct1) {
2252
+ k_argsort_f32_i32<GGML_SORT_ORDER_ASC>(
2253
+ x, dst, ncols, ncols_pad, item_ct1,
2254
+ dpct_local_acc_ct1.get_multi_ptr<sycl::access::decorated::no>()
2255
+ .get());
2256
+ });
2257
+ });
2258
+ } else if (order == GGML_SORT_ORDER_DESC) {
2259
+ stream->submit([&](sycl::handler &cgh) {
2260
+ sycl::local_accessor<uint8_t, 1> dpct_local_acc_ct1(
2261
+ sycl::range<1>(shared_mem), cgh);
2262
+
2263
+ cgh.parallel_for(
2264
+ sycl::nd_range<3>(block_nums * block_dims, block_dims),
2265
+ [=](sycl::nd_item<3> item_ct1) {
2266
+ k_argsort_f32_i32<GGML_SORT_ORDER_DESC>(
2267
+ x, dst, ncols, ncols_pad, item_ct1,
2268
+ dpct_local_acc_ct1.get_multi_ptr<sycl::access::decorated::no>()
2269
+ .get());
2270
+ });
2271
+ });
2272
+ } else {
2273
+ GGML_ABORT("fatal error");
2274
+ }
2275
+ }
2276
+
2277
+ static void argmax_f32_i32_sycl(const float *x, int *dst, const int ncols,
2278
+ const int nrows, queue_ptr stream) {
2279
+ const sycl::range<3> block_dims(1, 1, SYCL_ARGMAX_BLOCK_SIZE);
2280
+ const sycl::range<3> block_nums(1, nrows, 1);
2281
+ const size_t shared_mem = 256 * sizeof(float);
2282
+
2283
+ stream->submit([&](sycl::handler &cgh) {
2284
+ sycl::local_accessor<float, 1> shared_data(
2285
+ sycl::range<1>(shared_mem/sizeof(float)), cgh);
2286
+ sycl::local_accessor<int, 1> shared_indices(
2287
+ sycl::range<1>(shared_mem/sizeof(float)), cgh);
2288
+
2289
+ cgh.parallel_for(
2290
+ sycl::nd_range<3>(block_nums * block_dims, block_dims),
2291
+ [=](sycl::nd_item<3> item_ct1) {
2292
+ const int tid = item_ct1.get_local_id(2);
2293
+ const int row = item_ct1.get_global_id(1);
2294
+
2295
+ float max_val = -INFINITY;
2296
+ int max_idx = -1;
2297
+
2298
+ for (int col = tid; col < ncols; col += 256) {
2299
+ float val = x[row * ncols + col];
2300
+ if (val > max_val) {
2301
+ max_val = val;
2302
+ max_idx = col;
2303
+ }
2304
+ }
2305
+
2306
+ shared_data[tid] = max_val;
2307
+ shared_indices[tid] = max_idx;
2308
+ item_ct1.barrier(sycl::access::fence_space::local_space);
2309
+
2310
+ for (int stride = 256/2; stride > 0; stride >>= 1) {
2311
+ if (tid < stride) {
2312
+ float val1 = shared_data[tid];
2313
+ float val2 = shared_data[tid + stride];
2314
+ if (val2 > val1) {
2315
+ shared_data[tid] = val2;
2316
+ shared_indices[tid] = shared_indices[tid + stride];
2317
+ }
2318
+ }
2319
+ item_ct1.barrier(sycl::access::fence_space::local_space);
2320
+ }
2321
+
2322
+
2323
+ if (tid == 0) {
2324
+ dst[row] = shared_indices[0];
2325
+ }
2326
+ });
2327
+ });
2328
+ }
2329
+ static void diag_mask_inf_f32_sycl(const float *x, float *dst,
2330
+ const int ncols_x, const int nrows_x,
2331
+ const int rows_per_channel, const int n_past,
2332
+ queue_ptr stream) {
2333
+ const sycl::range<3> block_dims(1, SYCL_DIAG_MASK_INF_BLOCK_SIZE, 1);
2334
+ const int block_num_x = (ncols_x + SYCL_DIAG_MASK_INF_BLOCK_SIZE - 1) / SYCL_DIAG_MASK_INF_BLOCK_SIZE;
2335
+ const sycl::range<3> block_nums(1, block_num_x, nrows_x);
2336
+ stream->parallel_for(sycl::nd_range<3>(block_nums * block_dims, block_dims),
2337
+ [=](sycl::nd_item<3> item_ct1) {
2338
+ diag_mask_inf_f32(x, dst, ncols_x,
2339
+ rows_per_channel, n_past,
2340
+ item_ct1);
2341
+ });
2342
+ }
2343
+
2344
+ static dpct::err0 ggml_sycl_cpy_tensor_2d(void *dst,
2345
+ const struct ggml_tensor *src,
2346
+ int64_t i3, int64_t i2,
2347
+ int64_t i1_low, int64_t i1_high,
2348
+ queue_ptr stream) try {
2349
+
2350
+ dpct::memcpy_direction kind;
2351
+ char * src_ptr;
2352
+ if (src->backend == GGML_BACKEND_TYPE_CPU) {
2353
+ kind = dpct::host_to_device;
2354
+ src_ptr = (char *) src->data;
2355
+ // GGML_SYCL_DEBUG("ggml_sycl_cpy_tensor_2d GGML_BACKEND_TYPE_CPU src_ptr %p\n", src_ptr);
2356
+ } else if (src->backend == GGML_BACKEND_TYPE_GPU || src->backend == GGML_BACKEND_TYPE_GPU_SPLIT) {
2357
+ GGML_ASSERT(src->backend != GGML_BACKEND_TYPE_GPU_SPLIT || (i1_low == 0 && i1_high == src->ne[1]));
2358
+ kind = dpct::device_to_device;
2359
+ ggml_tensor_extra_gpu * extra = (ggml_tensor_extra_gpu *) src->extra;
2360
+ int id;
2361
+ SYCL_CHECK(CHECK_TRY_ERROR(
2362
+ id = get_current_device_id()));
2363
+ // GGML_SYCL_DEBUG("current device index %d\n", id);
2364
+ src_ptr = (char *) extra->data_device[id];
2365
+ } else {
2366
+ // GGML_SYCL_DEBUG("GGML_ABORT("fatal error")\n");
2367
+ GGML_ABORT("fatal error");
2368
+ }
2369
+ char * dst_ptr = (char *) dst;
2370
+
2371
+ GGML_TENSOR_LOCALS_1(int64_t, ne, src, ne);
2372
+ GGML_TENSOR_LOCALS(int64_t, nb, src, nb);
2373
+ const enum ggml_type type = src->type;
2374
+ const int64_t ts = ggml_type_size(type);
2375
+ const int64_t bs = ggml_blck_size(type);
2376
+ int64_t i1_diff = i1_high - i1_low;
2377
+
2378
+ const char * x = src_ptr + i1_low*nb1 + i2*nb2 + i3*nb3;
2379
+ if (nb0 == ts && nb1 == ts*ne0/bs) {
2380
+ // GGML_SYCL_DEBUG("stream->memcpy: dst_ptr=%p, x=%p, size=%lu\n", dst_ptr, x, i1_diff * nb1);
2381
+ // return CHECK_TRY_ERROR(stream->memcpy(dst_ptr, x, i1_diff * nb1));
2382
+ return CHECK_TRY_ERROR(dpct::async_dpct_memcpy(dst_ptr, x, i1_diff * nb1,
2383
+ kind, *stream));
2384
+
2385
+ } else if (nb0 == ts) {
2386
+ return CHECK_TRY_ERROR(
2387
+ dpct::async_dpct_memcpy(dst_ptr, ts * ne0 / bs, x, nb1,
2388
+ ts * ne0 / bs, i1_diff, kind, *stream));
2389
+ } else {
2390
+ for (int64_t i1 = 0; i1 < i1_diff; i1++) {
2391
+ const void * rx = (const void *) ((const char *) x + i1*nb1);
2392
+ void * rd = (void *) (dst_ptr + i1*ts*ne0/bs);
2393
+ // pretend the row is a matrix with cols=1
2394
+ dpct::err0 r = CHECK_TRY_ERROR(dpct::async_dpct_memcpy(
2395
+ rd, ts / bs, rx, nb0, ts / bs, ne0, kind, *stream));
2396
+ /*
2397
+ DPCT1001:85: The statement could not be removed.
2398
+ */
2399
+ /*
2400
+ DPCT1000:86: Error handling if-stmt was detected but could not be
2401
+ rewritten.
2402
+ */
2403
+ if (r != 0) return r;
2404
+ }
2405
+ return 0;
2406
+ }
2407
+ }
2408
+ catch (sycl::exception const &exc) {
2409
+ std::cerr << exc.what() << "Exception caught at file:" << __FILE__
2410
+ << ", line:" << __LINE__ << std::endl;
2411
+ std::exit(1);
2412
+ }
2413
+
2414
+ static void ggml_sycl_op_get_rows(ggml_backend_sycl_context & ctx, const ggml_tensor *src0,
2415
+ const ggml_tensor *src1, ggml_tensor *dst,
2416
+ const float *src0_d, const float *src1_d,
2417
+ float *dst_d, const queue_ptr &stream) {
2418
+
2419
+ GGML_ASSERT(src1->type == GGML_TYPE_I32);
2420
+ GGML_ASSERT(dst->type == GGML_TYPE_F32);
2421
+
2422
+ GGML_ASSERT(src0->nb[0] == ggml_type_size(src0->type));
2423
+ GGML_ASSERT(src1->nb[0] == ggml_type_size(src1->type));
2424
+ GGML_ASSERT(dst->nb[0] == ggml_type_size(dst->type));
2425
+
2426
+ const int32_t * src1_i32 = (const int32_t *) src1_d;
2427
+
2428
+ switch (src0->type) {
2429
+ case GGML_TYPE_F16:
2430
+ get_rows_sycl_float(ctx, src0, src1, dst, (const sycl::half *)src0_d,
2431
+ src1_i32, dst_d, stream);
2432
+ break;
2433
+ case GGML_TYPE_F32:
2434
+ get_rows_sycl_float(ctx, src0, src1, dst, src0_d, src1_i32, dst_d, stream);
2435
+ break;
2436
+ case GGML_TYPE_Q4_0:
2437
+ get_rows_sycl<QK4_0, QR4_0, dequantize_q4_0>(ctx, src0, src1, dst, src0_d, src1_i32, dst_d, stream);
2438
+ break;
2439
+ case GGML_TYPE_Q4_1:
2440
+ get_rows_sycl<QK4_1, QR4_1, dequantize_q4_1>(ctx, src0, src1, dst, src0_d, src1_i32, dst_d, stream);
2441
+ break;
2442
+ case GGML_TYPE_Q5_0:
2443
+ get_rows_sycl<QK5_0, QR5_0, dequantize_q5_0>(ctx, src0, src1, dst, src0_d, src1_i32, dst_d, stream);
2444
+ break;
2445
+ case GGML_TYPE_Q5_1:
2446
+ get_rows_sycl<QK5_1, QR5_1, dequantize_q5_1>(ctx, src0, src1, dst, src0_d, src1_i32, dst_d, stream);
2447
+ break;
2448
+ case GGML_TYPE_Q8_0:
2449
+ get_rows_sycl<QK8_0, QR8_0, dequantize_q8_0>(ctx, src0, src1, dst, src0_d, src1_i32, dst_d, stream);
2450
+ break;
2451
+ default:
2452
+ // TODO: k-quants
2453
+ GGML_LOG_ERROR("%s: unsupported type: %s\n", __func__, ggml_type_name(src0->type));
2454
+ GGML_ABORT("fatal error");
2455
+ break;
2456
+ }
2457
+ }
2458
+
2459
+
2460
+ static void ggml_sycl_op_repeat(ggml_backend_sycl_context & ctx, const ggml_tensor *src0,
2461
+ const ggml_tensor *src1, ggml_tensor *dst,
2462
+ const float *src0_d, const float *src1_d,
2463
+ float *dst_d,
2464
+ const queue_ptr &main_stream) {
2465
+
2466
+ ggml_sycl_op_bin_bcast<bin_bcast_sycl<op_repeat>>(ctx, dst, src0, dst, nullptr, src0_d, dst_d, main_stream);
2467
+
2468
+ GGML_UNUSED(src1);
2469
+ GGML_UNUSED(src1_d);
2470
+ }
2471
+
2472
+
2473
+ inline void ggml_sycl_op_mul_mat_sycl(
2474
+ ggml_backend_sycl_context & ctx,
2475
+ const ggml_tensor *src0, const ggml_tensor *src1, ggml_tensor *dst,
2476
+ const char *src0_dd_i, const float *src1_ddf_i, const char *src1_ddq_i,
2477
+ float *dst_dd_i, const int64_t row_low, const int64_t row_high,
2478
+ const int64_t src1_ncols, const int64_t src1_padded_row_size,
2479
+ const queue_ptr &stream) try {
2480
+
2481
+ GGML_ASSERT(src0_dd_i != nullptr);
2482
+ GGML_ASSERT(src1_ddf_i != nullptr);
2483
+ GGML_ASSERT(dst_dd_i != nullptr);
2484
+
2485
+ const int64_t ne00 = src0->ne[0];
2486
+ const int64_t ne10 = src1->ne[0];
2487
+
2488
+
2489
+ const int64_t row_diff = row_high - row_low;
2490
+
2491
+ int id;
2492
+ SYCL_CHECK(
2493
+ CHECK_TRY_ERROR(id = get_current_device_id()));
2494
+ #if !GGML_SYCL_DNNL
2495
+ const int64_t ne0 = dst->ne[0];
2496
+ // the main device has a larger memory buffer to hold the results from all GPUs
2497
+ // ldc == nrows of the matrix that cuBLAS writes into
2498
+ int ldc = id == ctx.device ? ne0 : row_diff;
2499
+ #endif
2500
+
2501
+ #ifdef GGML_SYCL_F16
2502
+ bool use_fp16 = true; // TODO(Yu) SYCL capability check
2503
+ #else
2504
+ bool use_fp16 = false;
2505
+ #endif
2506
+ if ((src0->type == GGML_TYPE_F16 || ggml_is_quantized(src0->type)) &&
2507
+ use_fp16 && ggml_is_contiguous(src0) && row_diff == src0->ne[1] &&
2508
+ dst->op_params[0] == GGML_PREC_DEFAULT) {
2509
+
2510
+ // GGML_SYCL_DEBUG("ggml_sycl_op_mul_mat_sycl - fp16 path\n");
2511
+ ggml_sycl_pool_alloc<sycl::half> src0_as_f16(ctx.pool());
2512
+ if (src0->type != GGML_TYPE_F16) {
2513
+ const to_fp16_sycl_t to_fp16_sycl = ggml_get_to_fp16_sycl(src0->type);
2514
+ GGML_ASSERT(to_fp16_sycl != nullptr);
2515
+ size_t ne = row_diff*ne00;
2516
+ src0_as_f16.alloc(ne);
2517
+ to_fp16_sycl(src0_dd_i, src0_as_f16.get(), ne, stream);
2518
+ }
2519
+ const sycl::half *src0_ptr = src0->type == GGML_TYPE_F16
2520
+ ? (const sycl::half *)src0_dd_i
2521
+ : src0_as_f16.get();
2522
+
2523
+ ggml_sycl_pool_alloc<sycl::half> src1_as_f16(ctx.pool());
2524
+ if (src1->type != GGML_TYPE_F16) {
2525
+ const to_fp16_sycl_t to_fp16_sycl = ggml_get_to_fp16_sycl(src1->type);
2526
+ GGML_ASSERT(to_fp16_sycl != nullptr);
2527
+ size_t ne = src1_ncols*ne10;
2528
+ src1_as_f16.alloc(ne);
2529
+ to_fp16_sycl(src1_ddf_i, src1_as_f16.get(), ne, stream);
2530
+ }
2531
+ const sycl::half *src1_ptr = src1->type == GGML_TYPE_F16
2532
+ ? (const sycl::half *)src1->data + src1_padded_row_size
2533
+ : src1_as_f16.get();
2534
+ ggml_sycl_pool_alloc<sycl::half> dst_f16(ctx.pool(), row_diff * src1_ncols);
2535
+
2536
+ #if !GGML_SYCL_DNNL
2537
+ const sycl::half alpha_f16 = 1.0f;
2538
+ const sycl::half beta_f16 = 0.0f;
2539
+ SYCL_CHECK(CHECK_TRY_ERROR(dpct::gemm(
2540
+ *stream, oneapi::mkl::transpose::trans,
2541
+ oneapi::mkl::transpose::nontrans, row_diff, src1_ncols, ne10,
2542
+ &alpha_f16, src0_ptr, dpct::library_data_t::real_half, ne00,
2543
+ src1_ptr, dpct::library_data_t::real_half, ne10, &beta_f16,
2544
+ dst_f16.get(), dpct::library_data_t::real_half, ldc,
2545
+ dpct::library_data_t::real_half)));
2546
+ const to_fp32_sycl_t to_fp32_sycl = ggml_get_to_fp32_sycl(GGML_TYPE_F16);
2547
+ to_fp32_sycl(dst_f16.get(), dst_dd_i, row_diff*src1_ncols, stream);
2548
+ #else
2549
+ auto dnnl_stream = ctx.stream_dnnl(stream);
2550
+ DnnlGemmWrapper::row_gemm(dnnl_stream, false, true, src1_ncols, row_diff, ne10, src1_ptr, DnnlGemmWrapper::to_dt<sycl::half>(),
2551
+ src0_ptr, DnnlGemmWrapper::to_dt<sycl::half>(), dst_f16.get(), DnnlGemmWrapper::to_dt<sycl::half>());
2552
+ const to_fp32_sycl_t to_fp32_sycl = ggml_get_to_fp32_sycl(GGML_TYPE_F16);
2553
+ to_fp32_sycl(dst_f16.get(), dst_dd_i, row_diff* src1_ncols, stream);
2554
+ #endif
2555
+ }
2556
+ else {
2557
+ // GGML_SYCL_DEBUG("ggml_sycl_op_mul_mat_sycl - fp32 path\n");
2558
+ ggml_sycl_pool_alloc<float> src0_ddq_as_f32(ctx.pool());
2559
+ ggml_sycl_pool_alloc<float> src1_ddq_as_f32(ctx.pool());
2560
+ if (src0->type != GGML_TYPE_F32) {
2561
+ const to_fp32_sycl_t to_fp32_sycl = ggml_get_to_fp32_sycl(src0->type);
2562
+ GGML_ASSERT(to_fp32_sycl != nullptr);
2563
+ src0_ddq_as_f32.alloc(row_diff*ne00);
2564
+ to_fp32_sycl(src0_dd_i, src0_ddq_as_f32.get(), row_diff*ne00, stream);
2565
+ }
2566
+ if (src1->type != GGML_TYPE_F32) {
2567
+ const to_fp32_sycl_t to_fp32_sycl = ggml_get_to_fp32_sycl(src1->type);
2568
+ GGML_ASSERT(to_fp32_sycl != nullptr);
2569
+ src1_ddq_as_f32.alloc(src1_ncols*ne10);
2570
+ to_fp32_sycl(src1_ddf_i, src1_ddq_as_f32.get(), src1_ncols*ne10, stream);
2571
+ }
2572
+ const float * src0_ddf_i = src0->type == GGML_TYPE_F32 ? (const float *) src0_dd_i : src0_ddq_as_f32.get();
2573
+ const float * src1_ddf1_i = src1->type == GGML_TYPE_F32 ? (const float *) src1_ddf_i : src1_ddq_as_f32.get();
2574
+
2575
+ #if !GGML_SYCL_DNNL
2576
+ const float alpha = 1.0f;
2577
+ const float beta = 0.0f;
2578
+ # ifdef GGML_SYCL_NVIDIA
2579
+ SYCL_CHECK(CHECK_TRY_ERROR(oneapi::mkl::blas::column_major::gemm(
2580
+ oneapi::mkl::backend_selector<oneapi::mkl::backend::cublas>{ *stream }, oneapi::mkl::transpose::trans,
2581
+ oneapi::mkl::transpose::nontrans, row_diff, src1_ncols, ne10, dpct::get_value(&alpha, *stream), src0_ddf_i,
2582
+ ne00, src1_ddf1_i, ne10, dpct::get_value(&beta, *stream), dst_dd_i, ldc)));
2583
+ # else
2584
+ SYCL_CHECK(CHECK_TRY_ERROR(oneapi::mkl::blas::column_major::gemm(
2585
+ *stream, oneapi::mkl::transpose::trans, oneapi::mkl::transpose::nontrans, row_diff, src1_ncols, ne10,
2586
+ dpct::get_value(&alpha, *stream), src0_ddf_i, ne00, src1_ddf1_i, ne10, dpct::get_value(&beta, *stream),
2587
+ dst_dd_i, ldc)));
2588
+ # endif
2589
+ #else
2590
+ auto dnnl_stream = ctx.stream_dnnl(stream);
2591
+ DnnlGemmWrapper::row_gemm(dnnl_stream, false, true, src1_ncols, row_diff, ne10, src1_ddf1_i, DnnlGemmWrapper::to_dt<float>(),
2592
+ src0_ddf_i, DnnlGemmWrapper::to_dt<float>(), dst_dd_i, DnnlGemmWrapper::to_dt<float>());
2593
+ #endif
2594
+ }
2595
+ GGML_UNUSED(dst);
2596
+ GGML_UNUSED(src1_ddq_i);
2597
+ GGML_UNUSED(src1_padded_row_size);
2598
+ }
2599
+ catch (sycl::exception const &exc) {
2600
+ std::cerr << exc.what() << "Exception caught at file:" << __FILE__
2601
+ << ", line:" << __LINE__ << std::endl;
2602
+ std::exit(1);
2603
+ }
2604
+
2605
+ static void ggml_sycl_op_pool2d(ggml_backend_sycl_context & ctx, const ggml_tensor *src0,
2606
+ const ggml_tensor *src1, ggml_tensor *dst,
2607
+ const float *src0_dd, const float *src1_dd,
2608
+ float *dst_dd, const queue_ptr &main_stream) {
2609
+
2610
+ GGML_ASSERT(src0->type == GGML_TYPE_F32);
2611
+ GGML_ASSERT( dst->type == GGML_TYPE_F32);
2612
+
2613
+ const int32_t * opts = (const int32_t *)dst->op_params;
2614
+ enum ggml_op_pool op = static_cast<ggml_op_pool>(opts[0]);
2615
+ const int k0 = opts[1];
2616
+ const int k1 = opts[2];
2617
+ const int s0 = opts[3];
2618
+ const int s1 = opts[4];
2619
+ const int p0 = opts[5];
2620
+ const int p1 = opts[6];
2621
+
2622
+ const int64_t IH = src0->ne[1];
2623
+ const int64_t IW = src0->ne[0];
2624
+
2625
+ const int64_t N = dst->ne[3];
2626
+ const int64_t OC = dst->ne[2];
2627
+ const int64_t OH = dst->ne[1];
2628
+ const int64_t OW = dst->ne[0];
2629
+
2630
+ const int parallel_elements = N * OC * OH * OW;
2631
+ const int num_blocks = (parallel_elements + SYCL_POOL2D_BLOCK_SIZE - 1) / SYCL_POOL2D_BLOCK_SIZE;
2632
+ sycl::range<3> block_nums(1, 1, num_blocks);
2633
+ main_stream->parallel_for(
2634
+ sycl::nd_range<3>(block_nums *
2635
+ sycl::range<3>(1, 1, SYCL_IM2COL_BLOCK_SIZE),
2636
+ sycl::range<3>(1, 1, SYCL_IM2COL_BLOCK_SIZE)),
2637
+ [=](sycl::nd_item<3> item_ct1) {
2638
+ pool2d_nchw_kernel(IH, IW, OH, OW, k1, k0, s1, s0, p1, p0,
2639
+ parallel_elements, src0_dd, dst_dd, op,
2640
+ item_ct1);
2641
+ });
2642
+
2643
+ GGML_UNUSED(src1);
2644
+ GGML_UNUSED(src1_dd);
2645
+ GGML_UNUSED(ctx);
2646
+ }
2647
+
2648
+ inline void ggml_sycl_op_sum(ggml_backend_sycl_context & ctx, const ggml_tensor *src0,
2649
+ const ggml_tensor *src1, ggml_tensor *dst,
2650
+ const float *src0_dd, const float *src1_dd,
2651
+ float *dst_dd,
2652
+ const queue_ptr &main_stream) {
2653
+ GGML_ASSERT(src0->type == GGML_TYPE_F32);
2654
+ GGML_ASSERT( dst->type == GGML_TYPE_F32);
2655
+
2656
+ const int64_t ne = ggml_nelements(src0);
2657
+
2658
+ sum_rows_f32_sycl(src0_dd, dst_dd, ne, 1, main_stream);
2659
+
2660
+ GGML_UNUSED(src1);
2661
+ GGML_UNUSED(dst);
2662
+ GGML_UNUSED(src1_dd);
2663
+ GGML_UNUSED(ctx);
2664
+ }
2665
+
2666
+ inline void ggml_sycl_op_sum_rows(ggml_backend_sycl_context & ctx, const ggml_tensor *src0,
2667
+ const ggml_tensor *src1, ggml_tensor *dst,
2668
+ const float *src0_dd, const float *src1_dd,
2669
+ float *dst_dd,
2670
+ const queue_ptr &main_stream) {
2671
+
2672
+ GGML_ASSERT(src0->type == GGML_TYPE_F32);
2673
+ GGML_ASSERT( dst->type == GGML_TYPE_F32);
2674
+
2675
+ const int64_t ncols = src0->ne[0];
2676
+ const int64_t nrows = ggml_nrows(src0);
2677
+
2678
+ sum_rows_f32_sycl(src0_dd, dst_dd, ncols, nrows, main_stream);
2679
+
2680
+ GGML_UNUSED(src1);
2681
+ GGML_UNUSED(dst);
2682
+ GGML_UNUSED(src1_dd);
2683
+ GGML_UNUSED(ctx);
2684
+ }
2685
+
2686
+ inline void ggml_sycl_op_argsort(ggml_backend_sycl_context & ctx, const ggml_tensor *src0,
2687
+ const ggml_tensor *src1, ggml_tensor *dst,
2688
+ const float *src0_dd, const float *src1_dd,
2689
+ float *dst_dd,
2690
+ const queue_ptr &main_stream) {
2691
+
2692
+ GGML_ASSERT(src0->type == GGML_TYPE_F32);
2693
+ GGML_ASSERT( dst->type == GGML_TYPE_I32);
2694
+
2695
+ const int64_t ncols = src0->ne[0];
2696
+ const int64_t nrows = ggml_nrows(src0);
2697
+
2698
+ enum ggml_sort_order order = (enum ggml_sort_order) dst->op_params[0];
2699
+
2700
+ argsort_f32_i32_sycl(src0_dd, (int *)dst_dd, ncols, nrows, order, main_stream);
2701
+
2702
+ GGML_UNUSED(src1);
2703
+ GGML_UNUSED(dst);
2704
+ GGML_UNUSED(src1_dd);
2705
+ GGML_UNUSED(ctx);
2706
+ }
2707
+
2708
+ inline void ggml_sycl_op_argmax(ggml_backend_sycl_context & ctx, const ggml_tensor *src0,
2709
+ const ggml_tensor *src1, ggml_tensor *dst,
2710
+ const float *src0_dd, const float *src1_dd,
2711
+ float *dst_dd,
2712
+ const queue_ptr &main_stream) {
2713
+
2714
+ GGML_ASSERT(src0->type == GGML_TYPE_F32);
2715
+ GGML_ASSERT( dst->type == GGML_TYPE_I32);
2716
+
2717
+ const int64_t ncols = src0->ne[0];
2718
+ const int64_t nrows = ggml_nrows(src0);
2719
+
2720
+ argmax_f32_i32_sycl(src0_dd, (int *)dst_dd, ncols, nrows, main_stream);
2721
+
2722
+ GGML_UNUSED(src1);
2723
+ GGML_UNUSED(dst);
2724
+ GGML_UNUSED(src1_dd);
2725
+ GGML_UNUSED(ctx);
2726
+ }
2727
+
2728
+ inline void ggml_sycl_op_diag_mask_inf(ggml_backend_sycl_context & ctx, const ggml_tensor *src0,
2729
+ const ggml_tensor *src1,
2730
+ ggml_tensor *dst, const float *src0_dd,
2731
+ const float *src1_dd, float *dst_dd,
2732
+ const queue_ptr &main_stream) {
2733
+
2734
+ GGML_ASSERT(src0->type == GGML_TYPE_F32);
2735
+ GGML_ASSERT( dst->type == GGML_TYPE_F32);
2736
+
2737
+ const int64_t ne00 = src0->ne[0];
2738
+ const int64_t ne01 = src0->ne[1];
2739
+ const int nrows0 = ggml_nrows(src0);
2740
+
2741
+ const int n_past = ((int32_t *) dst->op_params)[0];
2742
+
2743
+ diag_mask_inf_f32_sycl(src0_dd, dst_dd, ne00, nrows0, ne01, n_past, main_stream);
2744
+
2745
+ GGML_UNUSED(src1);
2746
+ GGML_UNUSED(dst);
2747
+ GGML_UNUSED(src1_dd);
2748
+ GGML_UNUSED(ctx);
2749
+ }
2750
+
2751
+ inline void ggml_sycl_op_scale(ggml_backend_sycl_context & ctx, const ggml_tensor *src0, const ggml_tensor *src1,
2752
+ ggml_tensor *dst, const float *src0_dd,
2753
+ const float *src1_dd, float *dst_dd,
2754
+ const queue_ptr &main_stream) {
2755
+
2756
+ GGML_ASSERT(src0->type == GGML_TYPE_F32);
2757
+ GGML_ASSERT( dst->type == GGML_TYPE_F32);
2758
+
2759
+ float scale;
2760
+ memcpy(&scale, dst->op_params, sizeof(float));
2761
+
2762
+ scale_f32_sycl(src0_dd, dst_dd, scale, ggml_nelements(src0), main_stream);
2763
+ /*
2764
+ DPCT1010:87: SYCL uses exceptions to report errors and does not use the
2765
+ error codes. The call was replaced with 0. You need to rewrite this code.
2766
+ */
2767
+ SYCL_CHECK(0);
2768
+
2769
+ GGML_UNUSED(src1);
2770
+ GGML_UNUSED(dst);
2771
+ GGML_UNUSED(src1_dd);
2772
+ GGML_UNUSED(ctx);
2773
+ }
2774
+
2775
+ inline void ggml_sycl_op_clamp(ggml_backend_sycl_context & ctx, const ggml_tensor *src0, const ggml_tensor *src1,
2776
+ ggml_tensor *dst, const float *src0_dd,
2777
+ const float *src1_dd, float *dst_dd,
2778
+ const queue_ptr &main_stream) {
2779
+
2780
+ GGML_ASSERT(src0->type == GGML_TYPE_F32);
2781
+ GGML_ASSERT( dst->type == GGML_TYPE_F32);
2782
+
2783
+ float min;
2784
+ float max;
2785
+ memcpy(&min, dst->op_params, sizeof(float));
2786
+ memcpy(&max, (float *) dst->op_params + 1, sizeof(float));
2787
+
2788
+ clamp_f32_sycl(src0_dd, dst_dd, min, max, ggml_nelements(src0), main_stream);
2789
+ /*
2790
+ DPCT1010:88: SYCL uses exceptions to report errors and does not use the
2791
+ error codes. The call was replaced with 0. You need to rewrite this code.
2792
+ */
2793
+ SYCL_CHECK(0);
2794
+
2795
+ GGML_UNUSED(src1);
2796
+ GGML_UNUSED(dst);
2797
+ GGML_UNUSED(src1_dd);
2798
+ GGML_UNUSED(ctx);
2799
+ }
2800
+
2801
+ static void ggml_sycl_set_peer_access(const int n_tokens, int main_device) {
2802
+ static bool peer_access_enabled = false;
2803
+
2804
+ const bool enable_peer_access = n_tokens <= GGML_SYCL_PEER_MAX_BATCH_SIZE;
2805
+
2806
+ if (peer_access_enabled == enable_peer_access) {
2807
+ return;
2808
+ }
2809
+
2810
+ #ifdef NDEBUG
2811
+ for (int i = 0; i < ggml_sycl_info().device_count; ++i) {
2812
+ SYCL_CHECK(ggml_sycl_set_device(i));
2813
+ }
2814
+
2815
+ for (int i = 0; i < ggml_sycl_info().device_count; ++i) {
2816
+ SYCL_CHECK(ggml_sycl_set_device(i));
2817
+
2818
+ for (int id_other = 0; id_other < ggml_sycl_info().device_count; ++id_other) {
2819
+ if (i == id_other) {
2820
+ continue;
2821
+ }
2822
+ if (i != main_device && id_other != main_device) {
2823
+ continue;
2824
+ }
2825
+
2826
+ // int can_access_peer;
2827
+ // SYCL_CHECK(syclDeviceCanAccessPeer(&can_access_peer, id, id_other));
2828
+ // if (can_access_peer) {
2829
+ // if (enable_peer_access) {
2830
+ // SYCL_CHECK(syclDeviceEnablePeerAccess(id_other, 0));
2831
+ // } else {
2832
+ // SYCL_CHECK(syclDeviceDisablePeerAccess(id_other));
2833
+ // }
2834
+ // }
2835
+ }
2836
+ }
2837
+ #endif // NDEBUG
2838
+
2839
+ peer_access_enabled = enable_peer_access;
2840
+ }
2841
+
2842
+ static void ggml_sycl_op_mul_mat(ggml_backend_sycl_context & ctx, const ggml_tensor *src0,
2843
+ const ggml_tensor *src1, ggml_tensor *dst,
2844
+ ggml_sycl_op_mul_mat_t op,
2845
+ const bool convert_src1_to_q8_1) try {
2846
+
2847
+ GGML_TENSOR_LOCALS(int64_t, ne0, src0, ne);
2848
+
2849
+ GGML_TENSOR_LOCALS(int64_t, ne1, src1, ne);
2850
+ const int64_t nrows1 = ggml_nrows(src1);
2851
+
2852
+ GGML_ASSERT(ne03 == ne13);
2853
+
2854
+ const int64_t ne0 = dst->ne[0];
2855
+ const int64_t ne1 = dst->ne[1];
2856
+
2857
+ const int nb2 = dst->nb[2];
2858
+ const int nb3 = dst->nb[3];
2859
+
2860
+ GGML_ASSERT(dst->backend != GGML_BACKEND_TYPE_GPU_SPLIT);
2861
+ GGML_ASSERT(src1->backend != GGML_BACKEND_TYPE_GPU_SPLIT);
2862
+ GGML_ASSERT(src1->type == GGML_TYPE_F32 || (src1->ne[2] == 1 && src1->ne[3] == 1));
2863
+
2864
+ GGML_ASSERT(ne12 >= ne02 && ne12 % ne02 == 0);
2865
+
2866
+ const int64_t i02_divisor = ne12 / ne02;
2867
+
2868
+ const size_t src0_ts = ggml_type_size(src0->type);
2869
+ const size_t src0_bs = ggml_blck_size(src0->type);
2870
+ const size_t q8_1_ts = sizeof(block_q8_1);
2871
+ const size_t q8_1_bs = QK8_1;
2872
+
2873
+ ggml_tensor_extra_gpu * src0_extra = (ggml_tensor_extra_gpu *) src0->extra;
2874
+ ggml_tensor_extra_gpu * src1_extra = (ggml_tensor_extra_gpu *) src1->extra;
2875
+
2876
+ const bool src0_is_contiguous = ggml_is_contiguous(src0);
2877
+ const bool src1_is_contiguous = ggml_is_contiguous(src1);
2878
+
2879
+ int64_t src1_padded_col_size = GGML_PAD(ne10, MATRIX_ROW_PADDING);
2880
+
2881
+ const bool split = src0->backend == GGML_BACKEND_TYPE_GPU_SPLIT;
2882
+ GGML_ASSERT(!(split && ne02 > 1));
2883
+ GGML_ASSERT(!(split && ne03 > 1));
2884
+ GGML_ASSERT(!(split && ne02 < ne12));
2885
+
2886
+ std::array<float, GGML_SYCL_MAX_DEVICES> tensor_split;
2887
+ if (split) {
2888
+ // TODO: check that src0->buffer->buft is a split buffer type, replace GGML_BACKEND_TYPE_GPU_SPLIT check
2889
+ // GGML_ASSERT(src0->buffer != nullptr && src0->buffer->buft == ...);
2890
+ ggml_backend_sycl_split_buffer_type_context * buft_ctx = (ggml_backend_sycl_split_buffer_type_context *) src0->buffer->buft->context;
2891
+ tensor_split = buft_ctx->tensor_split;
2892
+ }
2893
+
2894
+ struct dev_data {
2895
+ ggml_sycl_pool_alloc<char> src0_dd_alloc;
2896
+ ggml_sycl_pool_alloc<float> src1_ddf_alloc;
2897
+ ggml_sycl_pool_alloc<char> src1_ddq_alloc;
2898
+ ggml_sycl_pool_alloc<float> dst_dd_alloc;
2899
+
2900
+ char *src0_dd = nullptr;
2901
+ float *src1_ddf = nullptr; // float
2902
+ char *src1_ddq = nullptr; // q8_1
2903
+ float *dst_dd = nullptr;
2904
+
2905
+ int64_t row_low;
2906
+ int64_t row_high;
2907
+ };
2908
+
2909
+ dev_data dev[GGML_SYCL_MAX_DEVICES];
2910
+
2911
+ int used_devices = 0;
2912
+ queue_ptr main_stream = ctx.stream();
2913
+
2914
+ for (int i = 0; i < ggml_sycl_info().device_count; ++i) {
2915
+ // by default, use all rows
2916
+ dev[i].row_low = 0;
2917
+ dev[i].row_high = ne01;
2918
+
2919
+ // for multi GPU, get the row boundaries from tensor split
2920
+ // and round to mul_mat_q tile sizes
2921
+ if (split) {
2922
+ const int64_t rounding = get_row_rounding(src0->type, tensor_split);
2923
+
2924
+ if (i != 0) {
2925
+ dev[i].row_low = ne01*tensor_split[i];
2926
+ if (dev[i].row_low < ne01) {
2927
+ dev[i].row_low -= dev[i].row_low % rounding;
2928
+ }
2929
+ }
2930
+
2931
+ if (i != ggml_sycl_info().device_count - 1) {
2932
+ dev[i].row_high = ne01*tensor_split[i + 1];
2933
+ if (dev[i].row_high < ne01) {
2934
+ dev[i].row_high -= dev[i].row_high % rounding;
2935
+ }
2936
+ }
2937
+ }
2938
+ }
2939
+
2940
+ for (int i = 0; i < ggml_sycl_info().device_count; ++i) {
2941
+ if ((!split && i != ctx.device) || dev[i].row_low == dev[i].row_high) {
2942
+ continue;
2943
+ }
2944
+
2945
+ used_devices++;
2946
+
2947
+ const bool src1_on_device = i == ctx.device;
2948
+ const bool dst_on_device = i == ctx.device;
2949
+
2950
+ ggml_sycl_set_device(i);
2951
+ queue_ptr stream = ctx.stream(i, 0);
2952
+
2953
+ if (src0_is_contiguous) {
2954
+ dev[i].src0_dd = (char *) src0->data;
2955
+ } else {
2956
+ dev[i].src0_dd = dev[i].src0_dd_alloc.alloc(ctx.pool(i), ggml_nbytes(src0));
2957
+ }
2958
+
2959
+ if (src1_on_device && src1_is_contiguous) {
2960
+ dev[i].src1_ddf = (float *) src1->data;
2961
+ } else {
2962
+ dev[i].src1_ddf = dev[i].src1_ddf_alloc.alloc(ctx.pool(i), ggml_nelements(src1));
2963
+ }
2964
+
2965
+ if (convert_src1_to_q8_1) {
2966
+ dev[i].src1_ddq = dev[i].src1_ddq_alloc.alloc(ctx.pool(i), nrows1*src1_padded_col_size*q8_1_ts/q8_1_bs);
2967
+
2968
+ if (src1_on_device && src1_is_contiguous) {
2969
+ quantize_row_q8_1_sycl(dev[i].src1_ddf, dev[i].src1_ddq, ne10, nrows1, src1_padded_col_size, stream);
2970
+ /*
2971
+ DPCT1010:90: SYCL uses exceptions to report errors and does not
2972
+ use the error codes. The call was replaced with 0. You need to
2973
+ rewrite this code.
2974
+ */
2975
+ SYCL_CHECK(0);
2976
+ }
2977
+ }
2978
+
2979
+ if (dst_on_device) {
2980
+ dev[i].dst_dd = (float *) dst->data;
2981
+ } else {
2982
+ const size_t size_dst_ddf = split ? (dev[i].row_high - dev[i].row_low)*ne1 : ggml_nelements(dst);
2983
+ dev[i].dst_dd = dev[i].dst_dd_alloc.alloc(ctx.pool(i), size_dst_ddf);
2984
+ }
2985
+ }
2986
+
2987
+ // if multiple devices are used they need to wait for the main device
2988
+ // here an event is recorded that signals that the main device has finished calculating the input data
2989
+ if (split && used_devices > 1) {
2990
+ ggml_sycl_set_device(ctx.device);
2991
+ /*
2992
+ DPCT1024:91: The original code returned the error code that was further
2993
+ consumed by the program logic. This original code was replaced with 0.
2994
+ You may need to rewrite the program logic consuming the error code.
2995
+ */
2996
+ SYCL_CHECK(CHECK_TRY_ERROR(
2997
+ *src0_extra->events[ctx.device][0] =
2998
+ ctx.stream()->ext_oneapi_submit_barrier()));
2999
+ }
3000
+
3001
+ const int64_t src1_col_stride = split && used_devices > 1 ? MUL_MAT_SRC1_COL_STRIDE : ne11;
3002
+ for (int64_t src1_col_0 = 0; src1_col_0 < ne11; src1_col_0 += src1_col_stride) {
3003
+ const int64_t is = split ? (src1_col_0/src1_col_stride) % GGML_SYCL_MAX_STREAMS : 0;
3004
+ const int64_t src1_ncols = src1_col_0 + src1_col_stride > ne11 ? ne11 - src1_col_0 : src1_col_stride;
3005
+
3006
+ for (int i = 0; i < ggml_sycl_info().device_count; ++i) {
3007
+ if ((!split && i != ctx.device) || dev[i].row_low == dev[i].row_high) {
3008
+ continue;
3009
+ }
3010
+
3011
+ const bool src1_on_device = i == ctx.device;
3012
+ const bool dst_on_device = i == ctx.device;
3013
+ const int64_t row_diff = dev[i].row_high - dev[i].row_low;
3014
+
3015
+ ggml_sycl_set_device(i);
3016
+ queue_ptr stream = ctx.stream(i, is);
3017
+
3018
+ // wait for main GPU data if necessary
3019
+ if (split && (i != ctx.device || is != 0)) {
3020
+ /*
3021
+ DPCT1009:163: SYCL uses exceptions to report errors and does not
3022
+ use the error codes. The original code was commented out and a
3023
+ warning string was inserted. You need to rewrite this code.
3024
+ */
3025
+ SYCL_CHECK(CHECK_TRY_ERROR(stream->ext_oneapi_submit_barrier(
3026
+ {*src0_extra->events[ctx.device][0]})));
3027
+ }
3028
+
3029
+ for (int64_t i0 = 0; i0 < ne13*ne12; ++i0) {
3030
+ const int64_t i03 = i0 / ne12;
3031
+ const int64_t i02 = i0 % ne12;
3032
+
3033
+ const size_t src1_ddq_i_offset = (i0*ne11 + src1_col_0) * src1_padded_col_size*q8_1_ts/q8_1_bs;
3034
+
3035
+ // for split tensors the data begins at i0 == i0_offset_low
3036
+ char * src0_dd_i = dev[i].src0_dd + (i0/i02_divisor) * (ne01*ne00*src0_ts)/src0_bs;
3037
+ float * src1_ddf_i = dev[i].src1_ddf + (i0*ne11 + src1_col_0) * ne10;
3038
+ char * src1_ddq_i = dev[i].src1_ddq + src1_ddq_i_offset;
3039
+ float * dst_dd_i = dev[i].dst_dd + (i0*ne1 + src1_col_0) * (dst_on_device ? ne0 : row_diff);
3040
+
3041
+ // the main device memory buffer can be on VRAM scratch, with space for all partial results
3042
+ // in that case an offset on dst_ddf_i is needed
3043
+ if (i == ctx.device) {
3044
+ dst_dd_i += dev[i].row_low; // offset is 0 if no tensor split
3045
+ }
3046
+
3047
+ // copy src0, src1 to device if necessary
3048
+ if (src1_is_contiguous) {
3049
+ if (i != ctx.device) {
3050
+ if (convert_src1_to_q8_1) {
3051
+ char * src1_ddq_i_source = dev[ctx.device].src1_ddq + src1_ddq_i_offset;
3052
+ SYCL_CHECK(CHECK_TRY_ERROR(stream->memcpy(
3053
+ src1_ddq_i, src1_ddq_i_source,
3054
+ src1_ncols * src1_padded_col_size * q8_1_ts /
3055
+ q8_1_bs).wait()));
3056
+ } else {
3057
+
3058
+ float * src1_ddf_i_source = (float *) src1_extra->data_device[ctx.device];
3059
+ src1_ddf_i_source += (i0*ne11 + src1_col_0) * ne10;
3060
+
3061
+ SYCL_CHECK(CHECK_TRY_ERROR(dev2dev_memcpy(*stream, *main_stream,
3062
+ src1_ddf_i, src1_ddf_i_source,
3063
+ src1_ncols * ne10 * sizeof(float))));
3064
+ }
3065
+ }
3066
+ } else if (src1_on_device && !src1_is_contiguous) {
3067
+ SYCL_CHECK(ggml_sycl_cpy_tensor_2d(
3068
+ src1_ddf_i, src1, i03, i02, src1_col_0, src1_col_0+src1_ncols, stream));
3069
+ } else {
3070
+ GGML_ABORT("fatal error");
3071
+ }
3072
+
3073
+ if (convert_src1_to_q8_1 && !src1_is_contiguous) {
3074
+ quantize_row_q8_1_sycl(src1_ddf_i, src1_ddq_i, ne10, src1_ncols, src1_padded_col_size, stream);
3075
+ /*
3076
+ DPCT1010:92: SYCL uses exceptions to report errors and does
3077
+ not use the error codes. The call was replaced with 0. You
3078
+ need to rewrite this code.
3079
+ */
3080
+ SYCL_CHECK(0);
3081
+ }
3082
+
3083
+ if (src1_col_0 == 0 && !src0_is_contiguous && i02 % i02_divisor == 0) {
3084
+ SYCL_CHECK(ggml_sycl_cpy_tensor_2d(src0_dd_i, src0, i03, i02/i02_divisor, dev[i].row_low, dev[i].row_high, stream));
3085
+ }
3086
+ if (src1->type == GGML_TYPE_F16) {
3087
+ src1_padded_col_size = (i0 * ne11 + src1_col_0) * ne10;
3088
+ }
3089
+ // do the computation
3090
+ SYCL_CHECK(CHECK_TRY_ERROR(op(ctx, src0, src1, dst, src0_dd_i, src1_ddf_i, src1_ddq_i, dst_dd_i,
3091
+ dev[i].row_low, dev[i].row_high, src1_ncols, src1_padded_col_size, stream)));
3092
+ /*
3093
+ DPCT1010:93: SYCL uses exceptions to report errors and does not
3094
+ use the error codes. The call was replaced with 0. You need to
3095
+ rewrite this code.
3096
+ */
3097
+ SYCL_CHECK(0);
3098
+
3099
+ // copy dst to host or other device if necessary
3100
+ if (!dst_on_device) {
3101
+ void * dst_off_device = dst->data;
3102
+ if (split) {
3103
+ // src0 = weight matrix is saved as a transposed matrix for better memory layout.
3104
+ // dst is NOT transposed.
3105
+ // The outputs of matrix matrix multiplications can therefore NOT simply be concatenated for >1 GPU.
3106
+ // Instead they need to be copied to the correct slice in ne0 = dst row index.
3107
+ // If dst is a vector with ne0 == 1 then you don't have to do this but it still produces correct results.
3108
+ float * dhf_dst_i = (float *) ((char *) dst_off_device + i02*nb2 + i03*nb3);
3109
+ GGML_ASSERT(dst->nb[1] == ne0*sizeof(float));
3110
+ dhf_dst_i += src1_col_0*ne0 + dev[i].row_low;
3111
+
3112
+ SYCL_CHECK(CHECK_TRY_ERROR(dpct::async_dpct_memcpy(
3113
+ dhf_dst_i, ne0 * sizeof(float), dst_dd_i,
3114
+ row_diff * sizeof(float), row_diff * sizeof(float),
3115
+ src1_ncols, dpct::device_to_device, *stream)));
3116
+ } else {
3117
+ float * dhf_dst_i = (float *) ((char *) dst_off_device + i02*nb2 + i03*nb3);
3118
+ GGML_ASSERT(dst->nb[1] == ne0*sizeof(float));
3119
+ dhf_dst_i += src1_col_0*ne0;
3120
+ SYCL_CHECK(CHECK_TRY_ERROR(
3121
+ stream->memcpy(dhf_dst_i, dst_dd_i,
3122
+ src1_ncols * ne0 * sizeof(float)).wait()));
3123
+ }
3124
+ }
3125
+
3126
+ // add event for the main device to wait on until other device is done
3127
+ if (split && (i != ctx.device || is != 0)) {
3128
+ /*
3129
+ DPCT1024:94: The original code returned the error code that
3130
+ was further consumed by the program logic. This original
3131
+ code was replaced with 0. You may need to rewrite the
3132
+ program logic consuming the error code.
3133
+ */
3134
+ SYCL_CHECK(CHECK_TRY_ERROR(
3135
+ *src0_extra->events[i][is] =
3136
+ stream->ext_oneapi_submit_barrier()));
3137
+ }
3138
+ }
3139
+ }
3140
+ }
3141
+
3142
+ // main device waits for all other devices to be finished
3143
+ if (split && ggml_sycl_info().device_count > 1) {
3144
+ int64_t is_max = (ne11 + MUL_MAT_SRC1_COL_STRIDE - 1) / MUL_MAT_SRC1_COL_STRIDE;
3145
+ is_max = is_max <= GGML_SYCL_MAX_STREAMS ? is_max : GGML_SYCL_MAX_STREAMS;
3146
+
3147
+ ggml_sycl_set_device(ctx.device);
3148
+ for (int i = 0; i < ggml_sycl_info().device_count; ++i) {
3149
+ if (dev[i].row_low == dev[i].row_high) {
3150
+ continue;
3151
+ }
3152
+ for (int64_t is = 0; is < is_max; ++is) {
3153
+ SYCL_CHECK(CHECK_TRY_ERROR(
3154
+ ctx.stream()->ext_oneapi_submit_barrier(
3155
+ {*src0_extra->events[i][is]})));
3156
+ }
3157
+ }
3158
+ }
3159
+ }
3160
+ catch (sycl::exception const &exc) {
3161
+ std::cerr << exc.what() << "Exception caught at file:" << __FILE__
3162
+ << ", line:" << __LINE__ << std::endl;
3163
+ std::exit(1);
3164
+ }
3165
+
3166
+
3167
+ static void ggml_sycl_repeat(ggml_backend_sycl_context & ctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) {
3168
+ GGML_SYCL_DEBUG("call %s\n", __func__);
3169
+ ggml_sycl_op_flatten(ctx, src0, src1, dst, ggml_sycl_op_repeat);
3170
+ GGML_SYCL_DEBUG("call %s done\n", __func__);
3171
+ }
3172
+
3173
+ static void ggml_sycl_get_rows(ggml_backend_sycl_context & ctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) {
3174
+ GGML_SYCL_DEBUG("call %s\n", __func__);
3175
+ ggml_sycl_op_flatten(ctx, src0, src1, dst, ggml_sycl_op_get_rows);
3176
+ GGML_SYCL_DEBUG("call %s done\n", __func__);
3177
+ }
3178
+
3179
+ static void ggml_sycl_norm(ggml_backend_sycl_context & ctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) {
3180
+ GGML_SYCL_DEBUG("call %s\n", __func__);
3181
+ ggml_sycl_op_flatten(ctx, src0, src1, dst, ggml_sycl_op_norm);
3182
+ GGML_SYCL_DEBUG("call %s done\n", __func__);
3183
+ }
3184
+
3185
+ static void ggml_sycl_rms_norm(ggml_backend_sycl_context & ctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) {
3186
+ GGML_SYCL_DEBUG("call %s\n", __func__);
3187
+ ggml_sycl_op_flatten(ctx, src0, src1, dst, ggml_sycl_op_rms_norm);
3188
+ GGML_SYCL_DEBUG("call %s done\n", __func__);
3189
+ }
3190
+
3191
+ static void ggml_sycl_group_norm(ggml_backend_sycl_context & ctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) {
3192
+ GGML_SYCL_DEBUG("call %s\n", __func__);
3193
+ ggml_sycl_op_flatten(ctx, src0, src1, dst, ggml_sycl_op_group_norm);
3194
+ GGML_SYCL_DEBUG("call %s done\n", __func__);
3195
+ }
3196
+
3197
+ static void ggml_sycl_mul_mat_vec_p021(ggml_backend_sycl_context & ctx, const ggml_tensor *src0,
3198
+ const ggml_tensor *src1,
3199
+ ggml_tensor *dst) try {
3200
+ GGML_ASSERT(ggml_is_permuted(src0) && ggml_is_permuted(src1));
3201
+ GGML_ASSERT(src0->backend != GGML_BACKEND_TYPE_GPU_SPLIT);
3202
+ GGML_ASSERT(src0->nb[0] <= src0->nb[1] && src0->nb[2] <= src0->nb[3]); // 0213 permutation
3203
+ GGML_ASSERT(src1->nb[0] <= src1->nb[1] && src1->nb[2] <= src1->nb[3]); // 0213 permutation
3204
+ GGML_ASSERT(src0->type == GGML_TYPE_F16);
3205
+ GGML_ASSERT(src1->type == GGML_TYPE_F32);
3206
+
3207
+ const int64_t ne00 = src0->ne[0];
3208
+ const int64_t ne01 = src0->ne[1];
3209
+ const int64_t ne02 = src0->ne[2];
3210
+
3211
+ const int64_t ne12 = src1->ne[2];
3212
+
3213
+ SYCL_CHECK(ggml_sycl_set_device(ctx.device));
3214
+ queue_ptr main_stream = ctx.stream();
3215
+
3216
+ void * src0_ddq = src0->data;
3217
+ float * src1_ddf = (float *) src1->data;
3218
+ float * dst_ddf = (float *) dst->data;
3219
+
3220
+ ggml_mul_mat_p021_f16_f32_sycl(src0_ddq, src1_ddf, dst_ddf, ne00, ne01, ne02, ne12, main_stream);
3221
+ }
3222
+ catch (sycl::exception const &exc) {
3223
+ std::cerr << exc.what() << "Exception caught at file:" << __FILE__
3224
+ << ", line:" << __LINE__ << std::endl;
3225
+ std::exit(1);
3226
+ }
3227
+
3228
+ static void ggml_sycl_mul_mat_vec_nc(ggml_backend_sycl_context & ctx, const ggml_tensor *src0,
3229
+ const ggml_tensor *src1,
3230
+ ggml_tensor *dst) try {
3231
+ GGML_ASSERT(!ggml_is_transposed(src0));
3232
+ GGML_ASSERT(!ggml_is_transposed(src1));
3233
+ GGML_ASSERT(!ggml_is_permuted(src0));
3234
+ GGML_ASSERT(src0->backend != GGML_BACKEND_TYPE_GPU_SPLIT);
3235
+ GGML_ASSERT(src0->type == GGML_TYPE_F16);
3236
+ GGML_ASSERT(src1->type == GGML_TYPE_F32);
3237
+
3238
+ const int64_t ne00 = src0->ne[0];
3239
+ const int64_t ne01 = src0->ne[1];
3240
+ const int64_t ne02 = src0->ne[2];
3241
+
3242
+ const int64_t nb01 = src0->nb[1];
3243
+ const int64_t nb02 = src0->nb[2];
3244
+
3245
+ const int64_t ne12 = src1->ne[2];
3246
+
3247
+ SYCL_CHECK(ggml_sycl_set_device(ctx.device));
3248
+ queue_ptr main_stream = ctx.stream();
3249
+
3250
+ void * src0_ddq = src0->data;
3251
+ float * src1_ddf = (float *) src1->data;
3252
+ float * dst_ddf = (float *) dst->data;
3253
+
3254
+ const int64_t row_stride_x = nb01 / sizeof(sycl::half);
3255
+ const int64_t channel_stride_x = nb02 / sizeof(sycl::half);
3256
+
3257
+ ggml_mul_mat_vec_nc_f16_f32_sycl(src0_ddq, src1_ddf, dst_ddf, ne00, ne01, row_stride_x, ne02, ne12, channel_stride_x, main_stream);
3258
+ }
3259
+ catch (sycl::exception const &exc) {
3260
+ std::cerr << exc.what() << "Exception caught at file:" << __FILE__
3261
+ << ", line:" << __LINE__ << std::endl;
3262
+ std::exit(1);
3263
+ }
3264
+
3265
+ static void k_compute_batched_ptrs(const sycl::half *src0_as_f16,
3266
+ const sycl::half *src1_as_f16, char *dst,
3267
+ const void **ptrs_src, void **ptrs_dst,
3268
+ int64_t ne12, int64_t ne13, int64_t ne23,
3269
+ size_t nb02, size_t nb03, size_t nb12,
3270
+ size_t nb13, size_t nbd2, size_t nbd3,
3271
+ int64_t r2, int64_t r3,
3272
+ const sycl::nd_item<3> &item_ct1) {
3273
+ int64_t i13 = item_ct1.get_group(2) * item_ct1.get_local_range(2) +
3274
+ item_ct1.get_local_id(2);
3275
+ int64_t i12 = item_ct1.get_group(1) * item_ct1.get_local_range(1) +
3276
+ item_ct1.get_local_id(1);
3277
+
3278
+ if (i13 >= ne13 || i12 >= ne12) {
3279
+ return;
3280
+ }
3281
+
3282
+ int64_t i03 = i13 / r3;
3283
+ int64_t i02 = i12 / r2;
3284
+
3285
+ ptrs_src[0*ne23 + i12 + i13*ne12] = (const char *) src0_as_f16 + i02*nb02 + i03*nb03;
3286
+ ptrs_src[1*ne23 + i12 + i13*ne12] = (const char *) src1_as_f16 + i12*nb12 + i13*nb13;
3287
+ ptrs_dst[0*ne23 + i12 + i13*ne12] = ( char *) dst + i12*nbd2 + i13*nbd3;
3288
+ }
3289
+
3290
+ static void ggml_sycl_mul_mat_batched_sycl(ggml_backend_sycl_context & ctx,
3291
+ const ggml_tensor *src0,
3292
+ const ggml_tensor *src1,
3293
+ ggml_tensor *dst) try {
3294
+ GGML_ASSERT(!ggml_is_transposed(src0));
3295
+ GGML_ASSERT(!ggml_is_transposed(src1));
3296
+ GGML_ASSERT(src0->backend != GGML_BACKEND_TYPE_GPU_SPLIT);
3297
+ GGML_ASSERT(src0->type == GGML_TYPE_F16);
3298
+
3299
+ GGML_TENSOR_BINARY_OP_LOCALS
3300
+
3301
+
3302
+ SYCL_CHECK(ggml_sycl_set_device(ctx.device));
3303
+ queue_ptr main_stream = ctx.stream();;
3304
+
3305
+ void * src0_ddq = src0->data;
3306
+ sycl::half *src0_as_f16 = (sycl::half *)src0_ddq;
3307
+ float * src1_ddf = (float *) src1->data;
3308
+ float * dst_ddf = (float *) dst->data;
3309
+
3310
+ // convert src1 to fp16
3311
+ ggml_sycl_pool_alloc<sycl::half> src1_f16_alloc(ctx.pool());
3312
+ if (src1->type != GGML_TYPE_F16) {
3313
+ const to_fp16_sycl_t to_fp16_sycl = ggml_get_to_fp16_sycl(src1->type);
3314
+ const int64_t ne_src1 = ggml_nelements(src1);
3315
+ src1_f16_alloc.alloc(ne_src1);
3316
+ GGML_ASSERT(to_fp16_sycl != nullptr);
3317
+ to_fp16_sycl(src1_ddf, src1_f16_alloc.get(), ne_src1, main_stream);
3318
+ }
3319
+ sycl::half *src1_f16 = src1->type == GGML_TYPE_F16 ? (sycl::half *)src1_ddf
3320
+ : src1_f16_alloc.get();
3321
+
3322
+ char * dst_t;
3323
+
3324
+ dpct::library_data_t cu_compute_type = dpct::library_data_t::real_float;
3325
+ dpct::library_data_t cu_data_type = dpct::library_data_t::real_float;
3326
+
3327
+ // dst strides
3328
+ size_t nbd2 = dst->nb[2];
3329
+ size_t nbd3 = dst->nb[3];
3330
+
3331
+ const float alpha_f32 = 1.0f;
3332
+ const float beta_f32 = 0.0f;
3333
+
3334
+ const void * alpha = &alpha_f32;
3335
+ const void * beta = &beta_f32;
3336
+
3337
+ dst_t = (char *) dst_ddf;
3338
+
3339
+ GGML_ASSERT(ne12 % ne02 == 0);
3340
+ GGML_ASSERT(ne13 % ne03 == 0);
3341
+
3342
+ // broadcast factors
3343
+ const int64_t r2 = ne12/ne02;
3344
+ const int64_t r3 = ne13/ne03;
3345
+
3346
+ if (r2 == 1 && r3 == 1 && ggml_is_contiguous_2(src0) && ggml_is_contiguous_2(src1)) {
3347
+ // there is no broadcast and src0, src1 are contiguous across dims 2, 3
3348
+ SYCL_CHECK(CHECK_TRY_ERROR(dpct::gemm_batch(
3349
+ *main_stream, oneapi::mkl::transpose::trans,
3350
+ oneapi::mkl::transpose::nontrans, ne01, ne11, ne10, alpha,
3351
+ (const char *)src0_as_f16, dpct::library_data_t::real_half,
3352
+ nb01 / nb00, nb02 / nb00,
3353
+ (const char *)src1_f16, dpct::library_data_t::real_half,
3354
+ nb11 / nb10, nb12 / nb10, beta,
3355
+ (char *)dst_t, cu_data_type, ne01, nb2 / nb0,
3356
+ ne12 * ne13, cu_compute_type)));
3357
+ } else {
3358
+ const int ne23 = ne12*ne13;
3359
+
3360
+ ggml_sycl_pool_alloc<const void *> ptrs_src(ctx.pool(), 2*ne23);
3361
+ ggml_sycl_pool_alloc< void *> ptrs_dst(ctx.pool(), 1*ne23);
3362
+
3363
+ sycl::range<3> block_dims(1, ne12, ne13);
3364
+ /*
3365
+ DPCT1049:47: The work-group size passed to the SYCL kernel may exceed
3366
+ the limit. To get the device limit, query
3367
+ info::device::max_work_group_size. Adjust the work-group size if needed.
3368
+ */
3369
+ {
3370
+ dpct::has_capability_or_fail(main_stream->get_device(),
3371
+ {sycl::aspect::fp16});
3372
+
3373
+ main_stream->submit([&](sycl::handler &cgh) {
3374
+ const void **ptrs_src_get = ptrs_src.get();
3375
+ void **ptrs_dst_get = ptrs_dst.get();
3376
+ size_t nb12_scaled = src1->type == GGML_TYPE_F16 ? nb12 : nb12 / 2;
3377
+ size_t nb13_scaled = src1->type == GGML_TYPE_F16 ? nb13 : nb13 / 2;
3378
+ cgh.parallel_for(sycl::nd_range<3>(block_dims, block_dims),
3379
+ [=](sycl::nd_item<3> item_ct1) {
3380
+ k_compute_batched_ptrs(
3381
+ src0_as_f16, src1_f16,
3382
+ dst_t, ptrs_src_get,
3383
+ ptrs_dst_get, ne12, ne13, ne23,
3384
+ nb02, nb03, nb12_scaled, nb13_scaled,
3385
+ nbd2, nbd3, r2, r3, item_ct1);
3386
+ });
3387
+ });
3388
+ }
3389
+ SYCL_CHECK(CHECK_TRY_ERROR(dpct::gemm_batch(
3390
+ *main_stream, oneapi::mkl::transpose::trans,
3391
+ oneapi::mkl::transpose::nontrans, ne01, ne11, ne10, alpha,
3392
+ (const void **)(ptrs_src.get() + 0 * ne23),
3393
+ dpct::library_data_t::real_half, nb01 / nb00,
3394
+ (const void **)(ptrs_src.get() + 1 * ne23),
3395
+ dpct::library_data_t::real_half, nb11 / nb10, beta,
3396
+ (void **)(ptrs_dst.get() + 0 * ne23), cu_data_type, ne01, ne23,
3397
+ cu_compute_type)));
3398
+ }
3399
+ }
3400
+ catch (sycl::exception const &exc) {
3401
+ std::cerr << exc.what() << "Exception caught at file:" << __FILE__
3402
+ << ", line:" << __LINE__ << std::endl;
3403
+ std::exit(1);
3404
+ }
3405
+
3406
+ inline bool ggml_sycl_supports_mmq(enum ggml_type type) {
3407
+ // TODO: accuracy issues in MMQ
3408
+ GGML_UNUSED(type);
3409
+ return false;
3410
+ }
3411
+
3412
+ bool ggml_sycl_supports_dmmv(enum ggml_type type) {
3413
+ switch (type) {
3414
+ case GGML_TYPE_Q4_0:
3415
+ case GGML_TYPE_Q4_1:
3416
+ case GGML_TYPE_Q5_0:
3417
+ case GGML_TYPE_Q5_1:
3418
+ case GGML_TYPE_Q8_0:
3419
+ case GGML_TYPE_Q2_K:
3420
+ case GGML_TYPE_Q3_K:
3421
+ case GGML_TYPE_Q4_K:
3422
+ case GGML_TYPE_Q5_K:
3423
+ case GGML_TYPE_Q6_K:
3424
+ case GGML_TYPE_F16:
3425
+ return true;
3426
+ default:
3427
+ return false;
3428
+ }
3429
+ }
3430
+
3431
+ static void ggml_sycl_mul_mat(ggml_backend_sycl_context & ctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) {
3432
+ const bool split = ggml_backend_buffer_is_sycl_split(src0->buffer);
3433
+ int64_t min_compute_capability = INT_MAX;
3434
+
3435
+ if (split) {
3436
+ ggml_backend_sycl_split_buffer_type_context * buft_ctx = (ggml_backend_sycl_split_buffer_type_context *) src0->buffer->buft->context;
3437
+ auto & tensor_split = buft_ctx->tensor_split;
3438
+ for (int id = 0; id < ggml_sycl_info().device_count; ++id) {
3439
+ // skip devices that are not going to do any work:
3440
+ if (tensor_split[id] >= (id + 1 < ggml_sycl_info().device_count ? tensor_split[id + 1] : 1.0f)) {
3441
+ continue;
3442
+ }
3443
+
3444
+ if (min_compute_capability > ggml_sycl_info().devices[id].cc) {
3445
+ min_compute_capability = ggml_sycl_info().devices[id].cc;
3446
+ }
3447
+ }
3448
+ } else {
3449
+ min_compute_capability = ggml_sycl_info().devices[ctx.device].cc;
3450
+ }
3451
+
3452
+ // check data types and tensor shapes for custom matrix multiplication kernels:
3453
+ bool use_dequantize_mul_mat_vec = ggml_sycl_supports_dmmv(src0->type)
3454
+ && src1->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32
3455
+ && src0->ne[0] % GGML_SYCL_DMMV_X == 0 && src1->ne[1] == 1;
3456
+
3457
+ bool use_mul_mat_vec_q = ggml_is_quantized(src0->type)
3458
+ && src1->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32
3459
+ && src1->ne[1] <= MMVQ_MAX_BATCH_SIZE;
3460
+
3461
+ bool use_mul_mat_q = ggml_sycl_supports_mmq(src0->type)
3462
+ && src1->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32;
3463
+
3464
+ // mmvq and mmq need the __dp4a instruction which is available for gen12+
3465
+ // Workaround in https://github.com/ggerganov/llama.cpp/commit/95f84d5ce8b449a9b16009434aca800df504a02e
3466
+ use_mul_mat_q = use_mul_mat_q && (src0->type != GGML_TYPE_IQ2_XXS);
3467
+ #ifdef SYCL_USE_XMX
3468
+ use_mul_mat_q = use_mul_mat_q && (src1->ne[1] <= MMQ_MAX_BATCH_SIZE);
3469
+ #endif // SYCL_USE_XMX
3470
+
3471
+ // mmvq path is faster in the CUDA backend.
3472
+ if (ctx.stream()->get_backend() == sycl::backend::ext_oneapi_cuda)
3473
+ use_dequantize_mul_mat_vec = use_dequantize_mul_mat_vec && !use_mul_mat_vec_q;
3474
+
3475
+ if (!split && src0->type == GGML_TYPE_F16 && ggml_is_permuted(src0) && ggml_is_permuted(src1) && src1->ne[1] == 1) {
3476
+ // TODO: Refactor and cleanup of mul mat dispatching.
3477
+ if (src0->ne[3] == 1 && src1->ne[3] == 1) {
3478
+ // KQ single-batch
3479
+ // mmv p021 was specific for these dimensions
3480
+ ggml_sycl_mul_mat_vec_p021(ctx, src0, src1, dst);
3481
+ } else {
3482
+ // The kernel from the if path is faster for that specific case, but does not support all mul mats.
3483
+ ggml_sycl_mul_mat_batched_sycl(ctx, src0, src1, dst);
3484
+ }
3485
+ } else if (!split && src0->type == GGML_TYPE_F16 && !ggml_is_contiguous(src0) && !ggml_is_transposed(src1) && src1->ne[1] == 1) {
3486
+ // KQV single-batch
3487
+ ggml_sycl_mul_mat_vec_nc(ctx, src0, src1, dst);
3488
+ } else if (!split && src0->type == GGML_TYPE_F16 && !ggml_is_transposed(src0) && !ggml_is_transposed(src1) && src1->ne[2]*src1->ne[3] > 1) {
3489
+ // KQ + KQV multi-batch
3490
+ ggml_sycl_mul_mat_batched_sycl(ctx, src0, src1, dst);
3491
+ } else if (use_dequantize_mul_mat_vec) {
3492
+ ggml_sycl_op_mul_mat(ctx, src0, src1, dst, ggml_sycl_op_dequantize_mul_mat_vec, false);
3493
+ } else if (use_mul_mat_vec_q) {
3494
+ ggml_sycl_op_mul_mat(ctx, src0, src1, dst, ggml_sycl_op_mul_mat_vec_q, true);
3495
+ } else if (use_mul_mat_q) {
3496
+ ggml_sycl_op_mul_mat(ctx, src0, src1, dst, ggml_sycl_op_mul_mat_q, true);
3497
+ } else {
3498
+ ggml_sycl_op_mul_mat(ctx, src0, src1, dst, ggml_sycl_op_mul_mat_sycl, false);
3499
+ }
3500
+ }
3501
+
3502
+
3503
+ struct mmid_row_mapping {
3504
+ int32_t i1;
3505
+ int32_t i2;
3506
+ };
3507
+
3508
+ __dpct_inline__ static void k_copy_src1_to_contiguous(
3509
+ const char *__restrict__ src1_original, char *__restrict__ src1_contiguous,
3510
+ int *__restrict__ cur_src1_row, mmid_row_mapping *__restrict__ row_mapping,
3511
+ const char *__restrict ids, int64_t i02, size_t ids_nb1, size_t ids_nb0,
3512
+ int64_t ne11, int64_t ne10, size_t nb11, size_t nb12,
3513
+ const sycl::nd_item<3> &item_ct1, int &src1_row) {
3514
+ int32_t iid1 = item_ct1.get_group(2);
3515
+ int32_t id = item_ct1.get_group(1);
3516
+
3517
+ const int32_t row_id_i = *(const int32_t *) (ids + iid1*ids_nb1 + id*ids_nb0);
3518
+
3519
+ if (row_id_i != i02) {
3520
+ return;
3521
+ }
3522
+
3523
+ const int64_t i11 = id % ne11;
3524
+ const int64_t i12 = iid1;
3525
+
3526
+ if (item_ct1.get_local_id(2) == 0) {
3527
+ src1_row =
3528
+ dpct::atomic_fetch_add<sycl::access::address_space::generic_space>(
3529
+ cur_src1_row, 1);
3530
+ row_mapping[src1_row] = {id, iid1};
3531
+ }
3532
+ /*
3533
+ DPCT1065:194: Consider replacing sycl::nd_item::barrier() with
3534
+ sycl::nd_item::barrier(sycl::access::fence_space::local_space) for better
3535
+ performance if there is no access to global memory.
3536
+ */
3537
+ item_ct1.barrier();
3538
+
3539
+ const float * src1_row_original = (const float *)(src1_original + i11*nb11 + i12*nb12);
3540
+ float * src1_row_contiguous = (float *)(src1_contiguous + src1_row*nb11);
3541
+
3542
+ #pragma unroll
3543
+ for (int i = item_ct1.get_local_id(2); i < ne10;
3544
+ i += item_ct1.get_local_range(2)) {
3545
+ src1_row_contiguous[i] = src1_row_original[i];
3546
+ }
3547
+ }
3548
+
3549
+ __dpct_inline__ static void k_copy_dst_from_contiguous(
3550
+ char *__restrict__ dst_original, const char *__restrict__ dst_contiguous,
3551
+ const mmid_row_mapping *__restrict__ row_mapping, int64_t ne0, size_t nb1,
3552
+ size_t nb2, const sycl::nd_item<3> &item_ct1) {
3553
+ int32_t i = item_ct1.get_group(2);
3554
+
3555
+ const int32_t i1 = row_mapping[i].i1;
3556
+ const int32_t i2 = row_mapping[i].i2;
3557
+
3558
+ const float * dst_row_contiguous = (const float *)(dst_contiguous + i*nb1);
3559
+ float * dst_row_original = (float *)(dst_original + i1*nb1 + i2*nb2);
3560
+
3561
+ #pragma unroll
3562
+ for (int j = item_ct1.get_local_id(2); j < ne0;
3563
+ j += item_ct1.get_local_range(2)) {
3564
+ dst_row_original[j] = dst_row_contiguous[j];
3565
+ }
3566
+ }
3567
+
3568
+ static void ggml_sycl_mul_mat_id(ggml_backend_sycl_context & ctx, const ggml_tensor *src0,
3569
+ const ggml_tensor *src1,
3570
+ ggml_tensor *dst) try {
3571
+ GGML_ASSERT(!ggml_backend_buffer_is_sycl_split(src0->buffer) && "mul_mat_id does not support split buffers");
3572
+
3573
+ const ggml_tensor *ids = dst->src[2];
3574
+ GGML_TENSOR_BINARY_OP_LOCALS
3575
+
3576
+ const queue_ptr stream = ctx.stream();
3577
+
3578
+ const int64_t n_as = ne02;
3579
+ const int64_t n_ids = ids->ne[0];
3580
+
3581
+ std::vector<char> ids_host(ggml_nbytes(ids));
3582
+ const char * ids_dev = (const char *) ids->data;
3583
+
3584
+ SYCL_CHECK(CHECK_TRY_ERROR(
3585
+ stream->memcpy(ids_host.data(), ids_dev, ggml_nbytes(ids))));
3586
+ SYCL_CHECK(CHECK_TRY_ERROR(stream->wait()));
3587
+
3588
+ ggml_tensor src0_row = *src0;
3589
+ ggml_tensor src1_row = *src1;
3590
+ ggml_tensor dst_row = *dst;
3591
+
3592
+ char *src0_original = (char *)src0->data;
3593
+ char *src1_original = (char *)src1->data;
3594
+ char *dst_original = (char *)dst->data;
3595
+
3596
+ src0_row.ne[2] = 1;
3597
+ src0_row.ne[3] = 1;
3598
+ src0_row.nb[3] = nb02;
3599
+
3600
+ src1_row.ne[1] = 1;
3601
+ src1_row.ne[2] = 1;
3602
+ src1_row.ne[3] = 1;
3603
+ src1_row.nb[2] = nb11;
3604
+ src1_row.nb[3] = nb11;
3605
+
3606
+ dst_row.ne[1] = 1;
3607
+ dst_row.ne[2] = 1;
3608
+ dst_row.ne[3] = 1;
3609
+ dst_row.nb[2] = nb1;
3610
+ dst_row.nb[3] = nb1;
3611
+ if (ne12 == 1) {
3612
+ for (int64_t iid1 = 0; iid1 < ids->ne[1]; iid1++) {
3613
+ for (int64_t id = 0; id < n_ids; id++) {
3614
+ const int32_t i02 = *(const int32_t *) (ids_host.data() + iid1*ids->nb[1] + id*ids->nb[0]);
3615
+ GGML_ASSERT(i02 >= 0 && i02 < n_as);
3616
+
3617
+ const int64_t i11 = id % ne11;
3618
+ const int64_t i12 = iid1;
3619
+
3620
+ const int64_t i1 = id;
3621
+ const int64_t i2 = i12;
3622
+
3623
+ src0_row.data = src0_original + i02*nb02;
3624
+ src1_row.data = src1_original + + i11*nb11 + i12*nb12;
3625
+ dst_row.data = dst_original + i1*nb1 + i2*nb2;
3626
+
3627
+ ggml_sycl_mul_mat(ctx, &src0_row, &src1_row, &dst_row);
3628
+ }
3629
+ }
3630
+ } else {
3631
+ ggml_sycl_pool_alloc<char> src1_contiguous(ctx.pool(), sizeof(float)*ggml_nelements(src1));
3632
+ ggml_sycl_pool_alloc<char> dst_contiguous(ctx.pool(), sizeof(float)*ggml_nelements(dst));
3633
+
3634
+ src1_row.data = src1_contiguous.get();
3635
+ dst_row.data = dst_contiguous.get();
3636
+
3637
+ for (int64_t i02 = 0; i02 < n_as; i02++) {
3638
+ int64_t num_src1_rows = 0;
3639
+ for (int64_t iid1 = 0; iid1 < ids->ne[1]; iid1++) {
3640
+ for (int64_t id = 0; id < n_ids; id++) {
3641
+ const int32_t row_id_i = *(const int32_t *) (ids_host.data() + iid1*ids->nb[1] + id*ids->nb[0]);
3642
+
3643
+ GGML_ASSERT(row_id_i >= 0 && row_id_i < n_as);
3644
+
3645
+ if (row_id_i != i02) {
3646
+ continue;
3647
+ }
3648
+
3649
+ num_src1_rows++;
3650
+ }
3651
+ }
3652
+
3653
+ if (num_src1_rows == 0) {
3654
+ continue;
3655
+ }
3656
+
3657
+
3658
+ ggml_sycl_pool_alloc<int> dev_cur_src1_row(ctx.pool(), 1);
3659
+ ggml_sycl_pool_alloc<mmid_row_mapping> dev_row_mapping(ctx.pool(), num_src1_rows);
3660
+ SYCL_CHECK(CHECK_TRY_ERROR(
3661
+ stream->memset(dev_cur_src1_row.get(), 0, sizeof(int))));
3662
+
3663
+ {
3664
+ sycl::range<3> block_dims(1, 1, std::min((unsigned int)ne10, 768u));
3665
+ sycl::range<3> grid_dims(1, n_ids, ids->ne[1]);
3666
+ stream->submit([&](sycl::handler &cgh) {
3667
+ sycl::local_accessor<int, 0> src1_row_acc(cgh);
3668
+
3669
+ char *__restrict src1_contiguous_get =
3670
+ src1_contiguous.get();
3671
+ int *__restrict dev_cur_src1_row_get =
3672
+ dev_cur_src1_row.get();
3673
+ mmid_row_mapping *__restrict dev_row_mapping_get =
3674
+ dev_row_mapping.get();
3675
+ size_t ids_nb_ct6 = ids->nb[1];
3676
+ size_t ids_nb_ct7 = ids->nb[0];
3677
+
3678
+ cgh.parallel_for(
3679
+ sycl::nd_range<3>(grid_dims * block_dims, block_dims),
3680
+ [=](sycl::nd_item<3> item_ct1) {
3681
+ k_copy_src1_to_contiguous(
3682
+ src1_original, src1_contiguous_get,
3683
+ dev_cur_src1_row_get,
3684
+ dev_row_mapping_get, ids_dev, i02,
3685
+ ids_nb_ct6, ids_nb_ct7, ne11, ne10, nb11, nb12,
3686
+ item_ct1, src1_row_acc);
3687
+ });
3688
+ });
3689
+ }
3690
+
3691
+ src0_row.data = src0_original + i02*nb02;
3692
+
3693
+ GGML_ASSERT(nb11 == sizeof(float)*ne10);
3694
+ GGML_ASSERT(nb1 == sizeof(float)*ne0);
3695
+ src1_row.ne[1] = num_src1_rows;
3696
+
3697
+ src1_row.nb[1] = nb11;
3698
+ src1_row.nb[2] = num_src1_rows*nb11;
3699
+ src1_row.nb[3] = num_src1_rows*nb11;
3700
+
3701
+ dst_row.ne[1] = num_src1_rows;
3702
+ dst_row.nb[1] = nb1;
3703
+ dst_row.nb[2] = num_src1_rows*nb1;
3704
+ dst_row.nb[3] = num_src1_rows*nb1;
3705
+
3706
+ ggml_sycl_mul_mat(ctx, &src0_row, &src1_row, &dst_row);
3707
+
3708
+ {
3709
+ sycl::range<3> block_dims(1, 1, std::min((unsigned int)ne0, 768u));
3710
+ sycl::range<3> grid_dims(1, 1, num_src1_rows);
3711
+ stream->submit([&](sycl::handler &cgh) {
3712
+ const char *__restrict dst_contiguous_get =
3713
+ dst_contiguous.get();
3714
+ const mmid_row_mapping *__restrict dev_row_mapping_get =
3715
+ dev_row_mapping.get();
3716
+
3717
+ cgh.parallel_for(
3718
+ sycl::nd_range<3>(grid_dims * block_dims, block_dims),
3719
+ [=](sycl::nd_item<3> item_ct1) {
3720
+ k_copy_dst_from_contiguous(dst_original,
3721
+ dst_contiguous_get,
3722
+ dev_row_mapping_get,
3723
+ ne0, nb1, nb2, item_ct1);
3724
+ });
3725
+ });
3726
+ }
3727
+ }
3728
+ }
3729
+ }
3730
+ catch (sycl::exception const &exc) {
3731
+ std::cerr << exc.what() << "Exception caught at file:" << __FILE__
3732
+ << ", line:" << __LINE__ << std::endl;
3733
+ std::exit(1);
3734
+ }
3735
+
3736
+ static void ggml_sycl_scale(ggml_backend_sycl_context & ctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) {
3737
+ ggml_sycl_op_flatten(ctx, src0, src1, dst, ggml_sycl_op_scale);
3738
+ }
3739
+
3740
+ static void ggml_sycl_clamp(ggml_backend_sycl_context & ctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) {
3741
+ ggml_sycl_op_flatten(ctx, src0, src1, dst, ggml_sycl_op_clamp);
3742
+ }
3743
+
3744
+ static void ggml_sycl_cpy(ggml_backend_sycl_context & ctx, const ggml_tensor *src0, const ggml_tensor *src1,
3745
+ ggml_tensor *dst) try {
3746
+ const int64_t ne = ggml_nelements(src0);
3747
+ GGML_ASSERT(ne == ggml_nelements(src1));
3748
+
3749
+ GGML_ASSERT(ggml_nbytes(src0) <= INT_MAX);
3750
+ GGML_ASSERT(ggml_nbytes(src1) <= INT_MAX);
3751
+
3752
+ GGML_TENSOR_BINARY_OP_LOCALS01;
3753
+
3754
+ SYCL_CHECK(ggml_sycl_set_device(ctx.device));
3755
+ queue_ptr main_stream = ctx.stream();
3756
+
3757
+ char * src0_ddc = (char *) src0->data;
3758
+ char * src1_ddc = (char *) src1->data;
3759
+
3760
+ if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_F32) {
3761
+ ggml_cpy_f32_f32_sycl (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
3762
+ } else if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_F16) {
3763
+ ggml_cpy_f32_f16_sycl (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
3764
+ } else if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_Q8_0) {
3765
+ ggml_cpy_f32_q8_0_sycl(src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
3766
+ } else if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_Q4_0) {
3767
+ ggml_cpy_f32_q4_0_sycl(src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
3768
+ } else if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_Q4_1) {
3769
+ ggml_cpy_f32_q4_1_sycl(src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
3770
+ } else if (src0->type == GGML_TYPE_F16 && src1->type == GGML_TYPE_F32) {
3771
+ ggml_cpy_f16_f32_sycl (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
3772
+ } else if (src0->type == GGML_TYPE_F16 && src1->type == GGML_TYPE_F16) {
3773
+ ggml_cpy_f16_f16_sycl (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
3774
+ } else if (src0->type == GGML_TYPE_I16 && src1->type == GGML_TYPE_I16) {
3775
+ ggml_cpy_i16_i16_sycl (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
3776
+ } else if (src0->type == GGML_TYPE_I32 && src1->type == GGML_TYPE_I32) {
3777
+ ggml_cpy_i32_i32_sycl (src0_ddc, src1_ddc, ne, ne00, ne01, ne02, nb00, nb01, nb02, nb03, ne10, ne11, ne12, nb10, nb11, nb12, nb13, main_stream);
3778
+ } else {
3779
+ GGML_LOG_ERROR("%s: unsupported type combination (%s to %s)\n", __func__,
3780
+ ggml_type_name(src0->type), ggml_type_name(src1->type));
3781
+ GGML_ABORT("fatal error");
3782
+ }
3783
+
3784
+ GGML_UNUSED(dst);
3785
+ }
3786
+ catch (sycl::exception const &exc) {
3787
+ std::cerr << exc.what() << "Exception caught at file:" << __FILE__
3788
+ << ", line:" << __LINE__ << std::endl;
3789
+ std::exit(1);
3790
+ }
3791
+
3792
+ static void ggml_sycl_dup(ggml_backend_sycl_context & ctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) {
3793
+ // TODO: why do we pass dst as src1 here?
3794
+ ggml_sycl_cpy(ctx, src0, dst, nullptr);
3795
+ GGML_UNUSED(src1);
3796
+ }
3797
+
3798
+ static void ggml_sycl_diag_mask_inf(ggml_backend_sycl_context & ctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) {
3799
+ ggml_sycl_op_flatten(ctx, src0, src1, dst, ggml_sycl_op_diag_mask_inf);
3800
+ }
3801
+
3802
+ static void ggml_sycl_soft_max(ggml_backend_sycl_context & ctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) {
3803
+ ggml_sycl_op_flatten(ctx, src0, src1, dst, ggml_sycl_op_soft_max);
3804
+ }
3805
+
3806
+ static void ggml_sycl_rope(ggml_backend_sycl_context & ctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) {
3807
+ GGML_ASSERT(ggml_is_contiguous(src0)); // TODO: this restriction is temporary until non-cont support is implemented
3808
+ ggml_sycl_op_flatten(ctx, src0, src1, dst, ggml_sycl_op_rope);
3809
+ }
3810
+
3811
+ static void ggml_sycl_pool2d(ggml_backend_sycl_context & ctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) {
3812
+ ggml_sycl_op_flatten(ctx, src0, src1, dst, ggml_sycl_op_pool2d);
3813
+ }
3814
+
3815
+ static void ggml_sycl_im2col(ggml_backend_sycl_context & ctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) {
3816
+ ggml_sycl_op_flatten(ctx, src0, src1, dst, ggml_sycl_op_im2col);
3817
+ }
3818
+
3819
+ static void ggml_sycl_sum(ggml_backend_sycl_context & ctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) {
3820
+ GGML_ASSERT(ggml_is_contiguous(src0));
3821
+ ggml_sycl_op_flatten(ctx, src0, src1, dst, ggml_sycl_op_sum);
3822
+ }
3823
+
3824
+ static void ggml_sycl_sum_rows(ggml_backend_sycl_context & ctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) {
3825
+ GGML_ASSERT(ggml_is_contiguous(src0));
3826
+ ggml_sycl_op_flatten(ctx, src0, src1, dst, ggml_sycl_op_sum_rows);
3827
+ }
3828
+
3829
+ static void ggml_sycl_argsort(ggml_backend_sycl_context & ctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) {
3830
+ GGML_ASSERT(ggml_is_contiguous(src0));
3831
+ ggml_sycl_op_flatten(ctx, src0, src1, dst, ggml_sycl_op_argsort);
3832
+ }
3833
+
3834
+ static void ggml_sycl_argmax(ggml_backend_sycl_context & ctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) {
3835
+ GGML_ASSERT(ggml_is_contiguous(src0));
3836
+ ggml_sycl_op_flatten(ctx, src0, src1, dst, ggml_sycl_op_argmax);
3837
+ }
3838
+
3839
+ static void ggml_sycl_nop(ggml_backend_sycl_context & ctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) {
3840
+ GGML_UNUSED(src0);
3841
+ GGML_UNUSED(src1);
3842
+ GGML_UNUSED(dst);
3843
+ GGML_UNUSED(ctx);
3844
+ }
3845
+
3846
+ void ggml_sycl_set_main_device(const int main_device) try {
3847
+ if (dpct::get_current_device_id() == static_cast<unsigned int> (main_device)) {
3848
+ return;
3849
+ }
3850
+ check_allow_gpu_index(main_device);
3851
+ dpct::select_device(main_device);
3852
+
3853
+ if (g_ggml_sycl_debug) {
3854
+ dpct::device_info prop;
3855
+ SYCL_CHECK(CHECK_TRY_ERROR(dpct::get_device_info(
3856
+ prop, dpct::dev_mgr::instance().get_device(main_device))));
3857
+ GGML_LOG_INFO("Using device %d (%s) as main device\n",
3858
+ main_device, prop.get_name());
3859
+ }
3860
+ }
3861
+ catch (sycl::exception const &exc) {
3862
+ std::cerr << exc.what() << "Exception caught at file:" << __FILE__
3863
+ << ", line:" << __LINE__ << std::endl;
3864
+ std::exit(1);
3865
+ }
3866
+
3867
+ bool ggml_sycl_compute_forward(ggml_backend_sycl_context & ctx, struct ggml_tensor * tensor) {
3868
+ if (!g_sycl_loaded) return false;
3869
+
3870
+ ggml_sycl_func_t func;
3871
+
3872
+ switch (tensor->op) {
3873
+ case GGML_OP_ARGMAX:
3874
+ func = ggml_sycl_argmax;
3875
+ break;
3876
+ case GGML_OP_CONV_TRANSPOSE_1D:
3877
+ func = ggml_sycl_op_conv_transpose_1d;
3878
+ break;
3879
+ case GGML_OP_REPEAT:
3880
+ func = ggml_sycl_repeat;
3881
+ break;
3882
+ case GGML_OP_GET_ROWS:
3883
+ func = ggml_sycl_get_rows;
3884
+ break;
3885
+ case GGML_OP_DUP:
3886
+ func = ggml_sycl_dup;
3887
+ break;
3888
+ case GGML_OP_ADD:
3889
+ case GGML_OP_ADD1: // TODO: more efficient implementation
3890
+ func = ggml_sycl_add;
3891
+ break;
3892
+ case GGML_OP_SUB:
3893
+ func = ggml_sycl_sub;
3894
+ break;
3895
+ case GGML_OP_ACC:
3896
+ func = ggml_sycl_acc;
3897
+ break;
3898
+ case GGML_OP_MUL:
3899
+ func = ggml_sycl_mul;
3900
+ break;
3901
+ case GGML_OP_LOG:
3902
+ func = ggml_sycl_log;
3903
+ break;
3904
+ case GGML_OP_DIV:
3905
+ func = ggml_sycl_div;
3906
+ break;
3907
+ case GGML_OP_UNARY:
3908
+ switch (ggml_get_unary_op(tensor)) {
3909
+ case GGML_UNARY_OP_NEG:
3910
+ func = ggml_sycl_neg;
3911
+ break;
3912
+ case GGML_UNARY_OP_STEP:
3913
+ func = ggml_sycl_step;
3914
+ break;
3915
+ case GGML_UNARY_OP_GELU:
3916
+ func = ggml_sycl_gelu;
3917
+ break;
3918
+ case GGML_UNARY_OP_SILU:
3919
+ func = ggml_sycl_silu;
3920
+ break;
3921
+ case GGML_UNARY_OP_GELU_QUICK:
3922
+ func = ggml_sycl_gelu_quick;
3923
+ break;
3924
+ case GGML_UNARY_OP_TANH:
3925
+ func = ggml_sycl_tanh;
3926
+ break;
3927
+ case GGML_UNARY_OP_RELU:
3928
+ func = ggml_sycl_relu;
3929
+ break;
3930
+ case GGML_UNARY_OP_SIGMOID:
3931
+ func = ggml_sycl_sigmoid;
3932
+ break;
3933
+ case GGML_UNARY_OP_HARDSIGMOID:
3934
+ func = ggml_sycl_hardsigmoid;
3935
+ break;
3936
+ case GGML_UNARY_OP_HARDSWISH:
3937
+ func = ggml_sycl_hardswish;
3938
+ break;
3939
+ case GGML_UNARY_OP_EXP:
3940
+ func = ggml_sycl_exp;
3941
+ break;
3942
+ default:
3943
+ return false;
3944
+ }
3945
+ break;
3946
+ case GGML_OP_NORM:
3947
+ func = ggml_sycl_norm;
3948
+ break;
3949
+ case GGML_OP_GROUP_NORM:
3950
+ func = ggml_sycl_group_norm;
3951
+ break;
3952
+ case GGML_OP_CONCAT:
3953
+ func = ggml_sycl_op_concat;
3954
+ break;
3955
+ case GGML_OP_UPSCALE:
3956
+ func = ggml_sycl_upscale;
3957
+ break;
3958
+ case GGML_OP_PAD:
3959
+ func = ggml_sycl_pad;
3960
+ break;
3961
+ case GGML_OP_LEAKY_RELU:
3962
+ func = ggml_sycl_leaky_relu;
3963
+ break;
3964
+ case GGML_OP_RMS_NORM:
3965
+ func = ggml_sycl_rms_norm;
3966
+ break;
3967
+ case GGML_OP_MUL_MAT:
3968
+ if (tensor->src[0]->ne[3] != tensor->src[1]->ne[3]) {
3969
+ return false;
3970
+ }
3971
+ func = ggml_sycl_mul_mat;
3972
+ break;
3973
+ case GGML_OP_MUL_MAT_ID:
3974
+ if (tensor->src[0]->ne[3] != tensor->src[1]->ne[3]) {
3975
+ return false;
3976
+ }
3977
+ func = ggml_sycl_mul_mat_id;
3978
+ break;
3979
+ case GGML_OP_OUT_PROD:
3980
+ func = ggml_sycl_op_out_prod;
3981
+ break;
3982
+ case GGML_OP_SCALE:
3983
+ func = ggml_sycl_scale;
3984
+ break;
3985
+ case GGML_OP_SQR:
3986
+ func = ggml_sycl_sqr;
3987
+ break;
3988
+ case GGML_OP_SQRT:
3989
+ func = ggml_sycl_sqrt;
3990
+ break;
3991
+ case GGML_OP_SIN:
3992
+ func = ggml_sycl_sin;
3993
+ break;
3994
+ case GGML_OP_COS:
3995
+ func = ggml_sycl_cos;
3996
+ break;
3997
+ case GGML_OP_CLAMP:
3998
+ func = ggml_sycl_clamp;
3999
+ break;
4000
+ case GGML_OP_CPY:
4001
+ func = ggml_sycl_cpy;
4002
+ break;
4003
+ case GGML_OP_CONT:
4004
+ func = ggml_sycl_dup;
4005
+ break;
4006
+ case GGML_OP_NONE:
4007
+ case GGML_OP_RESHAPE:
4008
+ case GGML_OP_VIEW:
4009
+ case GGML_OP_PERMUTE:
4010
+ case GGML_OP_TRANSPOSE:
4011
+ func = ggml_sycl_nop;
4012
+ break;
4013
+ case GGML_OP_DIAG_MASK_INF:
4014
+ func = ggml_sycl_diag_mask_inf;
4015
+ break;
4016
+ case GGML_OP_SOFT_MAX:
4017
+ func = ggml_sycl_soft_max;
4018
+ break;
4019
+ case GGML_OP_ROPE:
4020
+ func = ggml_sycl_rope;
4021
+ break;
4022
+ case GGML_OP_IM2COL:
4023
+ func = ggml_sycl_im2col;
4024
+ break;
4025
+ case GGML_OP_POOL_2D:
4026
+ func = ggml_sycl_pool2d;
4027
+ break;
4028
+ case GGML_OP_SUM:
4029
+ func = ggml_sycl_sum;
4030
+ break;
4031
+ case GGML_OP_SUM_ROWS:
4032
+ func = ggml_sycl_sum_rows;
4033
+ break;
4034
+ case GGML_OP_ARGSORT:
4035
+ func = ggml_sycl_argsort;
4036
+ break;
4037
+ case GGML_OP_TIMESTEP_EMBEDDING:
4038
+ func = ggml_sycl_op_timestep_embedding;
4039
+ break;
4040
+ case GGML_OP_RWKV_WKV6:
4041
+ func = ggml_sycl_op_rwkv_wkv6;
4042
+ break;
4043
+ default:
4044
+ return false;
4045
+ }
4046
+
4047
+ if (tensor->src[0] != nullptr && ggml_backend_buffer_is_sycl_split(tensor->src[0]->buffer)) {
4048
+ ggml_sycl_set_peer_access(tensor->src[1]->ne[1], ctx.device);
4049
+ }
4050
+
4051
+ func(ctx, tensor->src[0], tensor->src[1], tensor);
4052
+ return true;
4053
+ }
4054
+
4055
+ GGML_API void ggml_backend_sycl_get_device_description(int device, char *description,
4056
+ size_t description_size) try {
4057
+ GGML_SYCL_DEBUG("[SYCL] call ggml_backend_sycl_get_device_description\n");
4058
+ dpct::device_info prop;
4059
+ SYCL_CHECK(CHECK_TRY_ERROR(dpct::get_device_info(
4060
+ prop, dpct::dev_mgr::instance().get_device(device))));
4061
+ snprintf(description, description_size, "%s", prop.get_name());
4062
+ }
4063
+ catch (sycl::exception const &exc) {
4064
+ std::cerr << exc.what() << "Exception caught at file:" << __FILE__
4065
+ << ", line:" << __LINE__ << std::endl;
4066
+ std::exit(1);
4067
+ }
4068
+
4069
+ void ggml_backend_sycl_get_device_memory(int device, size_t *free,
4070
+ size_t *total) try {
4071
+ GGML_SYCL_DEBUG("[SYCL] call ggml_backend_sycl_get_device_memory\n");
4072
+ ggml_sycl_set_device(device);
4073
+
4074
+ /*
4075
+ DPCT1009:218: SYCL uses exceptions to report errors and does not use the
4076
+ error codes. The original code was commented out and a warning string was
4077
+ inserted. You need to rewrite this code.
4078
+ */
4079
+ /*
4080
+ DPCT1106:217: 'cudaMemGetInfo' was migrated with the Intel extensions for
4081
+ device information which may not be supported by all compilers or runtimes.
4082
+ You may need to adjust the code.
4083
+ */
4084
+ SYCL_CHECK(CHECK_TRY_ERROR(
4085
+ dpct::dev_mgr::instance().get_device(device).get_memory_info(*free, *total)));
4086
+ }
4087
+ catch (sycl::exception const &exc) {
4088
+ std::cerr << exc.what() << "Exception caught at file:" << __FILE__
4089
+ << ", line:" << __LINE__ << std::endl;
4090
+ std::exit(1);
4091
+ }
4092
+
4093
+ ////////////////////////////////////////////////////////////////////////////////
4094
+
4095
+ // backend
4096
+
4097
+ static const char * ggml_backend_sycl_get_name(ggml_backend_t backend) {
4098
+
4099
+ ggml_backend_sycl_context * sycl_ctx = (ggml_backend_sycl_context *)backend->context;
4100
+
4101
+ return sycl_ctx->name.c_str();
4102
+ }
4103
+
4104
+ static void ggml_backend_sycl_free(ggml_backend_t backend) {
4105
+ ggml_backend_sycl_context * sycl_ctx = (ggml_backend_sycl_context *)backend->context;
4106
+
4107
+ delete sycl_ctx;
4108
+ delete backend;
4109
+ }
4110
+
4111
+ static void ggml_backend_sycl_set_tensor_async(ggml_backend_t backend,
4112
+ ggml_tensor *tensor,
4113
+ const void *data, size_t offset,
4114
+ size_t size) try {
4115
+ ggml_backend_sycl_context * sycl_ctx = (ggml_backend_sycl_context *)backend->context;
4116
+ ggml_backend_buffer_t buf = tensor->view_src ? tensor->view_src->buffer : tensor->buffer;
4117
+
4118
+ GGML_ASSERT(buf->buft == ggml_backend_sycl_buffer_type(sycl_ctx->device) && "unsupported buffer type");
4119
+ const queue_ptr stream = sycl_ctx->stream(sycl_ctx->device, 0);
4120
+ SYCL_CHECK(CHECK_TRY_ERROR(
4121
+ (stream)->memcpy((char *)tensor->data + offset, data, size)));
4122
+ }
4123
+ catch (sycl::exception const &exc) {
4124
+ std::cerr << exc.what() << "Exception caught at file:" << __FILE__
4125
+ << ", line:" << __LINE__ << std::endl;
4126
+ std::exit(1);
4127
+ }
4128
+
4129
+ static void ggml_backend_sycl_get_tensor_async(ggml_backend_t backend,
4130
+ const ggml_tensor *tensor,
4131
+ void *data, size_t offset,
4132
+ size_t size) try {
4133
+ ggml_backend_sycl_context * sycl_ctx = (ggml_backend_sycl_context *)backend->context;
4134
+ ggml_backend_buffer_t buf = tensor->view_src ? tensor->view_src->buffer : tensor->buffer;
4135
+
4136
+ GGML_ASSERT(buf->buft == ggml_backend_sycl_buffer_type(sycl_ctx->device) && "unsupported buffer type");
4137
+ const queue_ptr stream = sycl_ctx->stream(sycl_ctx->device, 0);
4138
+ SYCL_CHECK(CHECK_TRY_ERROR((stream)->memcpy(
4139
+ data, (const char *)tensor->data + offset, size).wait()));
4140
+ }
4141
+ catch (sycl::exception const &exc) {
4142
+ std::cerr << exc.what() << "Exception caught at file:" << __FILE__
4143
+ << ", line:" << __LINE__ << std::endl;
4144
+ std::exit(1);
4145
+ }
4146
+
4147
+ static bool ggml_backend_sycl_cpy_tensor_async(ggml_backend_t backend,
4148
+ const ggml_tensor *src,
4149
+ ggml_tensor *dst) try {
4150
+ ggml_backend_sycl_context * sycl_ctx = (ggml_backend_sycl_context *)backend->context;
4151
+ if (dst->buffer->buft == ggml_backend_sycl_buffer_type(sycl_ctx->device) && ggml_backend_buffer_is_sycl(src->buffer)) {
4152
+ /*
4153
+ DPCT1009:215: SYCL uses exceptions to report errors and does not use the
4154
+ error codes. The original code was commented out and a warning string
4155
+ was inserted. You need to rewrite this code.
4156
+ */
4157
+ const queue_ptr stream = sycl_ctx->stream(sycl_ctx->device, 0);
4158
+ SYCL_CHECK(CHECK_TRY_ERROR((stream)->memcpy(
4159
+ dst->data, src->data, ggml_nbytes(dst)).wait()));
4160
+ return true;
4161
+ }
4162
+
4163
+ return false;
4164
+ }
4165
+ catch (sycl::exception const &exc) {
4166
+ std::cerr << exc.what() << "Exception caught at file:" << __FILE__
4167
+ << ", line:" << __LINE__ << std::endl;
4168
+ std::exit(1);
4169
+ }
4170
+
4171
+ static void ggml_backend_sycl_synchronize(ggml_backend_t backend) try {
4172
+ ggml_backend_sycl_context * sycl_ctx = (ggml_backend_sycl_context *)backend->context;
4173
+ const queue_ptr stream = sycl_ctx->stream(sycl_ctx->device, 0);
4174
+ SYCL_CHECK(CHECK_TRY_ERROR((stream)->wait()));
4175
+
4176
+ GGML_UNUSED(backend);
4177
+ }
4178
+ catch (sycl::exception const &exc) {
4179
+ std::cerr << exc.what() << "Exception caught at file:" << __FILE__
4180
+ << ", line:" << __LINE__ << std::endl;
4181
+ std::exit(1);
4182
+ }
4183
+
4184
+ static ggml_status ggml_backend_sycl_graph_compute(ggml_backend_t backend, ggml_cgraph * cgraph) {
4185
+ ggml_backend_sycl_context * sycl_ctx = (ggml_backend_sycl_context *)backend->context;
4186
+ ggml_sycl_set_main_device(sycl_ctx->device);
4187
+
4188
+
4189
+ for (int i = 0; i < cgraph->n_nodes; i++) {
4190
+ ggml_tensor * node = cgraph->nodes[i];
4191
+ if (ggml_is_empty(node) || node->op == GGML_OP_RESHAPE || node->op == GGML_OP_TRANSPOSE || node->op == GGML_OP_VIEW || node->op == GGML_OP_PERMUTE || node->op == GGML_OP_NONE) {
4192
+ continue;
4193
+ }
4194
+ #ifndef NDEBUG
4195
+ assert(node->buffer->buft == ggml_backend_sycl_buffer_type(sycl_ctx->device));
4196
+ for (int j = 0; j < GGML_MAX_SRC; j++) {
4197
+ if (node->src[j] != nullptr) {
4198
+ assert(node->src[j]->buffer->buft == ggml_backend_sycl_buffer_type(sycl_ctx->device));
4199
+ }
4200
+ }
4201
+ #endif
4202
+ bool ok = ggml_sycl_compute_forward(*sycl_ctx, node);
4203
+ if (!ok) {
4204
+ GGML_LOG_ERROR("%s: error: op not supported %s (%s)\n", __func__, node->name, ggml_op_name(node->op));
4205
+ }
4206
+ GGML_ASSERT(ok);
4207
+ }
4208
+
4209
+ return GGML_STATUS_SUCCESS;
4210
+ }
4211
+
4212
+ static void ggml_backend_sycl_event_record(ggml_backend_t backend, ggml_backend_event_t event)
4213
+ try
4214
+ {
4215
+ ggml_backend_sycl_context *sycl_ctx =
4216
+ (ggml_backend_sycl_context *)backend->context;
4217
+
4218
+ sycl::event *sycl_event = static_cast<sycl::event *>(event->context);
4219
+
4220
+ const queue_ptr &stream = sycl_ctx->stream(sycl_ctx->device, 0);
4221
+ // Record the current state of the queue
4222
+ SYCL_CHECK(CHECK_TRY_ERROR(*sycl_event = stream->ext_oneapi_submit_barrier()));
4223
+ }
4224
+ catch (sycl::exception const &exc)
4225
+ {
4226
+ std::cerr << exc.what() << "Exception caught at file:" << __FILE__
4227
+ << ", line:" << __LINE__ << std::endl;
4228
+ std::exit(1);
4229
+ }
4230
+
4231
+ static void ggml_backend_sycl_event_wait(ggml_backend_t backend, ggml_backend_event_t event) try {
4232
+
4233
+ sycl::event* sycl_event = static_cast<sycl::event*>(event->context);
4234
+
4235
+ if (ggml_backend_is_sycl(backend)) {
4236
+ SYCL_CHECK(CHECK_TRY_ERROR(sycl_event->wait()));
4237
+ } else
4238
+ GGML_ABORT("fatal error");
4239
+ } catch (sycl::exception const& exc) {
4240
+ std::cerr << exc.what() << "Exception caught at file:" << __FILE__
4241
+ << ", line:" << __LINE__ << std::endl;
4242
+ std::exit(1);
4243
+ }
4244
+
4245
+ static ggml_backend_i ggml_backend_sycl_interface = {
4246
+ /* .get_name = */ ggml_backend_sycl_get_name,
4247
+ /* .free = */ ggml_backend_sycl_free,
4248
+ /* .set_tensor_async = */ ggml_backend_sycl_set_tensor_async,
4249
+ /* .get_tensor_async = */ ggml_backend_sycl_get_tensor_async,
4250
+ /* .cpy_tensor_async = */ NULL, // ggml_backend_sycl_cpy_tensor_async,
4251
+ // // TODO: update for the new
4252
+ // interface
4253
+ /* .synchronize = */ ggml_backend_sycl_synchronize,
4254
+ /* .graph_plan_create = */ NULL,
4255
+ /* .graph_plan_free = */ NULL,
4256
+ /* .graph_plan_update = */ NULL,
4257
+ /* .graph_plan_compute = */ NULL,
4258
+ /* .graph_compute = */ ggml_backend_sycl_graph_compute,
4259
+ /* .event_record = */ ggml_backend_sycl_event_record,
4260
+ /* .event_wait = */ ggml_backend_sycl_event_wait,
4261
+ };
4262
+
4263
+ static ggml_guid_t ggml_backend_sycl_guid() {
4264
+ static ggml_guid guid = { 0x58, 0x05, 0x13, 0x8f, 0xcd, 0x3a, 0x61, 0x9d, 0xe7, 0xcd, 0x98, 0xa9, 0x03, 0xfd, 0x7c, 0x53 };
4265
+ return &guid;
4266
+ }
4267
+
4268
+ bool ggml_backend_is_sycl(ggml_backend_t backend) {
4269
+ return backend != NULL && ggml_guid_matches(backend->guid, ggml_backend_sycl_guid());
4270
+ }
4271
+
4272
+ int ggml_backend_sycl_get_device_count() {
4273
+ GGML_SYCL_DEBUG("[SYCL] call ggml_backend_sycl_get_device_count\n");
4274
+ return ggml_sycl_info().device_count;
4275
+ }
4276
+
4277
+
4278
+ // backend device
4279
+
4280
+ struct ggml_backend_sycl_device_context {
4281
+ int device;
4282
+ std::string name;
4283
+ std::string description;
4284
+ };
4285
+
4286
+ static const char * ggml_backend_sycl_device_get_name(ggml_backend_dev_t dev) {
4287
+ ggml_backend_sycl_device_context * ctx = (ggml_backend_sycl_device_context *)dev->context;
4288
+ return ctx->name.c_str();
4289
+ }
4290
+
4291
+ static const char * ggml_backend_sycl_device_get_description(ggml_backend_dev_t dev) {
4292
+ ggml_backend_sycl_device_context * ctx = (ggml_backend_sycl_device_context *)dev->context;
4293
+ return ctx->description.c_str();
4294
+ }
4295
+
4296
+ static void ggml_backend_sycl_device_get_memory(ggml_backend_dev_t dev, size_t * free, size_t * total) {
4297
+ ggml_backend_sycl_device_context * ctx = (ggml_backend_sycl_device_context *)dev->context;
4298
+ ggml_sycl_set_device(ctx->device);
4299
+ SYCL_CHECK(CHECK_TRY_ERROR(
4300
+ dpct::dev_mgr::instance().get_device(ctx->device).get_memory_info(*free, *total)));
4301
+ }
4302
+
4303
+ static enum ggml_backend_dev_type ggml_backend_sycl_device_get_type(ggml_backend_dev_t dev) {
4304
+ GGML_UNUSED(dev);
4305
+ return GGML_BACKEND_DEVICE_TYPE_GPU;
4306
+ }
4307
+
4308
+ static void ggml_backend_sycl_device_get_props(ggml_backend_dev_t dev, ggml_backend_dev_props * props) {
4309
+ props->name = ggml_backend_sycl_device_get_name(dev);
4310
+ props->description = ggml_backend_sycl_device_get_description(dev);
4311
+ props->type = ggml_backend_sycl_device_get_type(dev);
4312
+ ggml_backend_sycl_device_get_memory(dev, &props->memory_free, &props->memory_total);
4313
+
4314
+ bool host_buffer = getenv("GGML_SYCL_NO_PINNED") == nullptr;
4315
+ #ifdef GGML_SYCL_NO_PEER_COPY
4316
+ bool events = false;
4317
+ #else
4318
+ bool events = true;
4319
+ #endif
4320
+
4321
+ props->caps = {
4322
+ /* .async = */ true,
4323
+ /* .host_buffer = */ host_buffer,
4324
+ /* .buffer_from_host_ptr = */ false,
4325
+ /* .events = */ events,
4326
+ };
4327
+ }
4328
+
4329
+ static ggml_backend_t ggml_backend_sycl_device_init(ggml_backend_dev_t dev, const char * params) {
4330
+ GGML_UNUSED(params);
4331
+ ggml_backend_sycl_device_context * ctx = (ggml_backend_sycl_device_context *)dev->context;
4332
+ return ggml_backend_sycl_init(ctx->device);
4333
+ }
4334
+
4335
+ static ggml_backend_buffer_type_t ggml_backend_sycl_device_get_buffer_type(ggml_backend_dev_t dev) {
4336
+ ggml_backend_sycl_device_context * ctx = (ggml_backend_sycl_device_context *)dev->context;
4337
+ return ggml_backend_sycl_buffer_type(ctx->device);
4338
+ }
4339
+
4340
+ static ggml_backend_buffer_type_t ggml_backend_sycl_device_get_host_buffer_type(ggml_backend_dev_t dev) {
4341
+ GGML_UNUSED(dev);
4342
+ return ggml_backend_sycl_host_buffer_type();
4343
+ }
4344
+
4345
+ static ggml_backend_buffer_t ggml_backend_sycl_device_buffer_from_host_ptr(ggml_backend_dev_t dev, void * ptr, size_t size, size_t max_tensor_size) {
4346
+ GGML_UNUSED(dev);
4347
+ GGML_UNUSED(ptr);
4348
+ GGML_UNUSED(size);
4349
+ GGML_UNUSED(max_tensor_size);
4350
+ return nullptr;
4351
+ }
4352
+
4353
+ static bool ggml_backend_sycl_device_supports_op(ggml_backend_dev_t dev, const ggml_tensor * op) {
4354
+ switch (op->op) {
4355
+ case GGML_OP_CONV_TRANSPOSE_1D:
4356
+ {
4357
+ ggml_type src0_type = op->src[0]->type;
4358
+ ggml_type src1_type = op->src[1]->type;
4359
+ if (src0_type == GGML_TYPE_F32 && src1_type == GGML_TYPE_F32) {
4360
+ return true;
4361
+ }
4362
+ return false;
4363
+ } break;
4364
+ case GGML_OP_UNARY:
4365
+ switch (ggml_get_unary_op(op)) {
4366
+ case GGML_UNARY_OP_NEG:
4367
+ case GGML_UNARY_OP_STEP:
4368
+ case GGML_UNARY_OP_GELU:
4369
+ case GGML_UNARY_OP_SILU:
4370
+ case GGML_UNARY_OP_RELU:
4371
+ case GGML_UNARY_OP_SIGMOID:
4372
+ case GGML_UNARY_OP_HARDSIGMOID:
4373
+ case GGML_UNARY_OP_HARDSWISH:
4374
+ case GGML_UNARY_OP_GELU_QUICK:
4375
+ case GGML_UNARY_OP_TANH:
4376
+ case GGML_UNARY_OP_EXP:
4377
+ return ggml_is_contiguous(op->src[0]);
4378
+ default:
4379
+ return false;
4380
+ }
4381
+ break;
4382
+ case GGML_OP_MUL_MAT:
4383
+ case GGML_OP_MUL_MAT_ID:
4384
+ {
4385
+ struct ggml_tensor * a;
4386
+ struct ggml_tensor * b;
4387
+ if (op->op == GGML_OP_MUL_MAT) {
4388
+ a = op->src[0];
4389
+ b = op->src[1];
4390
+ } else {
4391
+ a = op->src[2];
4392
+ b = op->src[1];
4393
+ }
4394
+ if (a->ne[3] != b->ne[3]) {
4395
+ return false;
4396
+ }
4397
+ ggml_type a_type = a->type;
4398
+ if (a_type == GGML_TYPE_IQ4_NL || a_type == GGML_TYPE_IQ4_XS ||
4399
+ a_type == GGML_TYPE_IQ3_XXS || a_type == GGML_TYPE_IQ3_S ||
4400
+ a_type == GGML_TYPE_IQ2_XXS || a_type == GGML_TYPE_IQ2_XS || a_type == GGML_TYPE_IQ2_S ||
4401
+ a_type == GGML_TYPE_IQ1_S || a_type == GGML_TYPE_IQ1_M
4402
+ ) {
4403
+ if (b->ne[1] == 1 && ggml_nrows(b) > 1) {
4404
+ return false;
4405
+ }
4406
+ }
4407
+ ggml_type src0_type = op->src[0]->type;
4408
+ if (src0_type == GGML_TYPE_BF16) {
4409
+ return false;
4410
+ }
4411
+ return true;
4412
+ } break;
4413
+ case GGML_OP_OUT_PROD:
4414
+ return op->type == GGML_TYPE_F32 && op->src[0]->type == GGML_TYPE_F32 && op->src[1]->type == GGML_TYPE_F32 && op->ne[2] == 1 && op->ne[3] == 1;
4415
+ case GGML_OP_GET_ROWS:
4416
+ {
4417
+ switch (op->src[0]->type) {
4418
+ case GGML_TYPE_F16:
4419
+ case GGML_TYPE_F32:
4420
+ case GGML_TYPE_Q4_0:
4421
+ case GGML_TYPE_Q4_1:
4422
+ case GGML_TYPE_Q5_0:
4423
+ case GGML_TYPE_Q5_1:
4424
+ case GGML_TYPE_Q8_0:
4425
+ return true;
4426
+ default:
4427
+ return false;
4428
+ }
4429
+ } break;
4430
+ case GGML_OP_CPY:
4431
+ {
4432
+ ggml_type src0_type = op->src[0]->type;
4433
+ ggml_type src1_type = op->src[1]->type;
4434
+ if (src0_type == GGML_TYPE_F32 && src1_type == GGML_TYPE_F32) {
4435
+ return true;
4436
+ }
4437
+ if (src0_type == GGML_TYPE_F32 && src1_type == GGML_TYPE_F16) {
4438
+ return true;
4439
+ }
4440
+ if (src0_type == GGML_TYPE_F32 && src1_type == GGML_TYPE_Q8_0) {
4441
+ return true;
4442
+ }
4443
+ if (src0_type == GGML_TYPE_F32 && src1_type == GGML_TYPE_Q4_0) {
4444
+ return true;
4445
+ }
4446
+ if (src0_type == GGML_TYPE_F32 && src1_type == GGML_TYPE_Q4_1) {
4447
+ return true;
4448
+ }
4449
+ if (src0_type == GGML_TYPE_F16 && src1_type == GGML_TYPE_F16) {
4450
+ return true;
4451
+ }
4452
+ if (src0_type == GGML_TYPE_F16 && src1_type == GGML_TYPE_F32) {
4453
+ return true;
4454
+ }
4455
+ return false;
4456
+ } break;
4457
+ case GGML_OP_CONCAT:
4458
+ {
4459
+ ggml_type src0_type = op->src[0]->type;
4460
+ return src0_type != GGML_TYPE_I32 && src0_type != GGML_TYPE_I16;
4461
+ } break;
4462
+ case GGML_OP_DUP:
4463
+ case GGML_OP_ARGMAX:
4464
+ case GGML_OP_NONE:
4465
+ case GGML_OP_RESHAPE:
4466
+ case GGML_OP_REPEAT:
4467
+ case GGML_OP_VIEW:
4468
+ case GGML_OP_PERMUTE:
4469
+ case GGML_OP_TRANSPOSE:
4470
+ case GGML_OP_NORM:
4471
+ case GGML_OP_ADD:
4472
+ case GGML_OP_ADD1:
4473
+ case GGML_OP_LOG:
4474
+ case GGML_OP_SUB:
4475
+ case GGML_OP_MUL:
4476
+ case GGML_OP_DIV:
4477
+ case GGML_OP_RMS_NORM:
4478
+ case GGML_OP_SCALE:
4479
+ case GGML_OP_SQR:
4480
+ case GGML_OP_SQRT:
4481
+ case GGML_OP_SIN:
4482
+ case GGML_OP_COS:
4483
+ case GGML_OP_CLAMP:
4484
+ return true;
4485
+ case GGML_OP_CONT:
4486
+ return op->src[0]->type != GGML_TYPE_BF16;
4487
+ case GGML_OP_DIAG_MASK_INF:
4488
+ case GGML_OP_SOFT_MAX:
4489
+ return true;
4490
+ case GGML_OP_ROPE:
4491
+ {
4492
+ const int mode = ((const int32_t *) op->op_params)[2];
4493
+ if (mode & GGML_ROPE_TYPE_MROPE) {
4494
+ return false;
4495
+ }
4496
+ if (mode & GGML_ROPE_TYPE_VISION) {
4497
+ return false;
4498
+ }
4499
+ return ggml_is_contiguous(op->src[0]);
4500
+ }
4501
+ case GGML_OP_IM2COL:
4502
+ // TODO: add support for the new F32 operations
4503
+ return op->src[0]->type == GGML_TYPE_F16;
4504
+ case GGML_OP_POOL_2D:
4505
+ case GGML_OP_SUM:
4506
+ case GGML_OP_SUM_ROWS:
4507
+ case GGML_OP_ARGSORT:
4508
+ case GGML_OP_ACC:
4509
+ case GGML_OP_GROUP_NORM:
4510
+ case GGML_OP_UPSCALE:
4511
+ case GGML_OP_PAD:
4512
+ case GGML_OP_LEAKY_RELU:
4513
+ case GGML_OP_TIMESTEP_EMBEDDING:
4514
+ case GGML_OP_RWKV_WKV6:
4515
+ return true;
4516
+ default:
4517
+ return false;
4518
+ }
4519
+
4520
+ GGML_UNUSED(dev);
4521
+ }
4522
+
4523
+ static bool ggml_backend_sycl_device_supports_buft(ggml_backend_dev_t dev, ggml_backend_buffer_type_t buft) {
4524
+ if (buft->iface.get_name != ggml_backend_sycl_buffer_type_get_name) {
4525
+ return false;
4526
+ }
4527
+ ggml_backend_sycl_buffer_type_context * buft_ctx = (ggml_backend_sycl_buffer_type_context *)buft->context;
4528
+ ggml_backend_sycl_device_context * sycl_ctx = (ggml_backend_sycl_device_context *)dev->context;
4529
+ return buft_ctx->device == sycl_ctx->device;
4530
+ }
4531
+
4532
+ static int64_t get_op_batch_size(const ggml_tensor * op) {
4533
+ switch (op->op) {
4534
+ case GGML_OP_GET_ROWS:
4535
+ return 0;
4536
+ case GGML_OP_MUL_MAT:
4537
+ return op->ne[1];
4538
+ case GGML_OP_MUL_MAT_ID:
4539
+ case GGML_OP_ROPE:
4540
+ return op->ne[2];
4541
+ default:
4542
+ return ggml_nrows(op);
4543
+ }
4544
+ }
4545
+
4546
+ static bool ggml_backend_sycl_device_offload_op(ggml_backend_dev_t dev, const ggml_tensor * op) {
4547
+ const int min_batch_size = 32;
4548
+ return get_op_batch_size(op) >= min_batch_size;
4549
+ GGML_UNUSED(dev);
4550
+ }
4551
+
4552
+ static ggml_backend_event_t
4553
+ ggml_backend_sycl_device_event_new(ggml_backend_dev_t dev) {
4554
+
4555
+ #ifdef GGML_SYCL_NO_PEER_COPY
4556
+ return nullptr;
4557
+ #else
4558
+ sycl::event *event_ptr = new sycl::event();
4559
+
4560
+ return new ggml_backend_event{
4561
+ /* .device = */ dev,
4562
+ /* .context = */ event_ptr,
4563
+ };
4564
+ #endif
4565
+ }
4566
+
4567
+ static void ggml_backend_sycl_device_event_free(ggml_backend_dev_t dev, ggml_backend_event_t event) try {
4568
+ GGML_UNUSED(dev);
4569
+ if (event == nullptr) {
4570
+ return;
4571
+ }
4572
+
4573
+ if (event->context != nullptr) {
4574
+ sycl::event *sycl_event = static_cast<sycl::event *>(event->context);
4575
+ delete sycl_event;
4576
+ event->context = nullptr;
4577
+ }
4578
+
4579
+ delete event;
4580
+ } catch (sycl::exception const &exc) {
4581
+ std::cerr << exc.what() << "Exception caught at file:" << __FILE__
4582
+ << ", line:" << __LINE__ << std::endl;
4583
+ std::exit(1);
4584
+ }
4585
+
4586
+
4587
+ static void ggml_backend_sycl_device_event_synchronize(ggml_backend_dev_t dev, ggml_backend_event_t event) try {
4588
+ GGML_UNUSED(dev);
4589
+
4590
+ sycl::event *sycl_event = static_cast<sycl::event *>(event->context);
4591
+ SYCL_CHECK(CHECK_TRY_ERROR(sycl_event->wait()));
4592
+ } catch (sycl::exception const &exc) {
4593
+ std::cerr << exc.what() << "Exception caught at file:" << __FILE__
4594
+ << ", line:" << __LINE__ << std::endl;
4595
+ std::exit(1);
4596
+ }
4597
+
4598
+ static const ggml_backend_device_i ggml_backend_sycl_device_interface = {
4599
+ /* .get_name = */ ggml_backend_sycl_device_get_name,
4600
+ /* .get_description = */ ggml_backend_sycl_device_get_description,
4601
+ /* .get_memory = */ ggml_backend_sycl_device_get_memory,
4602
+ /* .get_type = */ ggml_backend_sycl_device_get_type,
4603
+ /* .get_props = */ ggml_backend_sycl_device_get_props,
4604
+ /* .init_backend = */ ggml_backend_sycl_device_init,
4605
+ /* .get_buffer_type = */ ggml_backend_sycl_device_get_buffer_type,
4606
+ /* .get_host_buffer_type = */ ggml_backend_sycl_device_get_host_buffer_type,
4607
+ /* .buffer_from_host_ptr = */ ggml_backend_sycl_device_buffer_from_host_ptr,
4608
+ /* .supports_op = */ ggml_backend_sycl_device_supports_op,
4609
+ /* .supports_buft = */ ggml_backend_sycl_device_supports_buft,
4610
+ /* .offload_op = */ ggml_backend_sycl_device_offload_op,
4611
+ /* .event_new = */ ggml_backend_sycl_device_event_new,
4612
+ /* .event_free = */ ggml_backend_sycl_device_event_free,
4613
+ /* .event_synchronize = */ ggml_backend_sycl_device_event_synchronize,
4614
+ };
4615
+
4616
+ // backend reg
4617
+
4618
+ struct ggml_backend_sycl_reg_context {
4619
+ std::vector<ggml_backend_dev_t> devices;
4620
+ };
4621
+
4622
+ static const char * ggml_backend_sycl_reg_get_name(ggml_backend_reg_t reg) {
4623
+ GGML_UNUSED(reg);
4624
+ return GGML_SYCL_NAME;
4625
+ }
4626
+
4627
+ static size_t ggml_backend_sycl_reg_get_device_count(ggml_backend_reg_t reg) {
4628
+ ggml_backend_sycl_reg_context * ctx = (ggml_backend_sycl_reg_context *)reg->context;
4629
+ return ctx->devices.size();
4630
+ }
4631
+
4632
+ static ggml_backend_dev_t ggml_backend_sycl_reg_get_device(ggml_backend_reg_t reg, size_t index) {
4633
+ ggml_backend_sycl_reg_context * ctx = (ggml_backend_sycl_reg_context *)reg->context;
4634
+ GGML_ASSERT(index < ctx->devices.size());
4635
+ return ctx->devices[index];
4636
+ }
4637
+
4638
+ static void *ggml_backend_sycl_reg_get_proc_address(ggml_backend_reg_t reg, const char *name) {
4639
+ GGML_UNUSED(reg);
4640
+
4641
+ // TODO: update to the current function signature
4642
+ //if (strcmp(name, "ggml_backend_split_buffer_type") == 0) {
4643
+ // return (void *)ggml_backend_sycl_split_buffer_type;
4644
+ //}
4645
+
4646
+ // SYCL doesn't support registering host memory, left here for reference
4647
+ // "ggml_backend_register_host_buffer"
4648
+ // "ggml_backend_unregister_host_buffer"
4649
+ GGML_UNUSED(name);
4650
+ return nullptr;
4651
+ }
4652
+
4653
+ static const ggml_backend_reg_i ggml_backend_sycl_reg_interface = {
4654
+ /* .get_name = */ ggml_backend_sycl_reg_get_name,
4655
+ /* .get_device_count = */ ggml_backend_sycl_reg_get_device_count,
4656
+ /* .get_device = */ ggml_backend_sycl_reg_get_device,
4657
+ /* .get_proc_address = */ ggml_backend_sycl_reg_get_proc_address,
4658
+ };
4659
+
4660
+
4661
+ // backend registry
4662
+
4663
+ ggml_backend_reg_t ggml_backend_sycl_reg() {
4664
+ static ggml_backend_reg reg;
4665
+ static bool initialized = false;
4666
+
4667
+ {
4668
+ static std::mutex mutex;
4669
+ std::lock_guard<std::mutex> lock(mutex);
4670
+ if (!initialized) {
4671
+ ggml_backend_sycl_reg_context * ctx = new ggml_backend_sycl_reg_context;
4672
+
4673
+ for (int i = 0; i < ggml_sycl_info().device_count; i++) {
4674
+ ggml_backend_sycl_device_context * dev_ctx = new ggml_backend_sycl_device_context;
4675
+ dev_ctx->device = i;
4676
+ dev_ctx->name = GGML_SYCL_NAME + std::to_string(i);
4677
+
4678
+ ggml_sycl_set_device(i);
4679
+
4680
+ dpct::device_info prop;
4681
+ SYCL_CHECK(CHECK_TRY_ERROR(dpct::get_device_info(
4682
+ prop, dpct::dev_mgr::instance().get_device(i))));
4683
+
4684
+ dev_ctx->description = prop.get_name();
4685
+
4686
+ ggml_backend_dev_t dev = new ggml_backend_device {
4687
+ /* .iface = */ ggml_backend_sycl_device_interface,
4688
+ /* .reg = */ &reg,
4689
+ /* .context = */ dev_ctx
4690
+ };
4691
+ ctx->devices.push_back(dev);
4692
+ }
4693
+
4694
+ reg = ggml_backend_reg {
4695
+ /* .api_version = */ GGML_BACKEND_API_VERSION,
4696
+ /* .iface = */ ggml_backend_sycl_reg_interface,
4697
+ /* .context = */ ctx
4698
+ };
4699
+ }
4700
+
4701
+ initialized = true;
4702
+ }
4703
+
4704
+ return &reg;
4705
+ }
4706
+
4707
+ ggml_backend_t ggml_backend_sycl_init(int device) {
4708
+ GGML_SYCL_DEBUG("[SYCL] call ggml_backend_sycl_init\n");
4709
+ ggml_check_sycl();
4710
+
4711
+ check_allow_gpu_index(device);
4712
+
4713
+ ggml_backend_sycl_context * ctx = new ggml_backend_sycl_context(device);
4714
+ if (ctx == nullptr) {
4715
+ GGML_LOG_ERROR("%s: error: failed to allocate context\n", __func__);
4716
+ return nullptr;
4717
+ };
4718
+
4719
+ ggml_backend_t sycl_backend = new ggml_backend {
4720
+ /* .guid = */ ggml_backend_sycl_guid(),
4721
+ /* .interface = */ ggml_backend_sycl_interface,
4722
+ /* .device = */ ggml_backend_reg_dev_get(ggml_backend_sycl_reg(), device),
4723
+ /* .context = */ ctx
4724
+ };
4725
+
4726
+ return sycl_backend;
4727
+ }
4728
+
4729
+ GGML_BACKEND_DL_IMPL(ggml_backend_sycl_reg)