whispercpp 1.3.0 → 1.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +5 -0
- data/LICENSE +1 -1
- data/README.md +165 -434
- data/Rakefile +60 -11
- data/ext/.gitignore +13 -0
- data/ext/cpu.mk +9 -0
- data/ext/{dr_wav.h → examples/dr_wav.h} +3560 -1179
- data/ext/extconf.rb +185 -16
- data/ext/ggml/include/ggml-alloc.h +76 -0
- data/ext/ggml/include/ggml-backend.h +352 -0
- data/ext/ggml/include/ggml-blas.h +25 -0
- data/ext/ggml/include/ggml-cann.h +123 -0
- data/ext/ggml/include/ggml-cpp.h +38 -0
- data/ext/ggml/include/ggml-cpu.h +135 -0
- data/ext/ggml/include/ggml-cuda.h +47 -0
- data/ext/ggml/include/ggml-kompute.h +50 -0
- data/ext/ggml/include/ggml-metal.h +66 -0
- data/ext/ggml/include/ggml-opencl.h +26 -0
- data/ext/ggml/include/ggml-opt.h +216 -0
- data/ext/ggml/include/ggml-rpc.h +28 -0
- data/ext/ggml/include/ggml-sycl.h +49 -0
- data/ext/ggml/include/ggml-vulkan.h +31 -0
- data/ext/{ggml.h → ggml/include/ggml.h} +479 -596
- data/ext/ggml/src/ggml-alloc.c +1037 -0
- data/ext/ggml/src/ggml-amx/common.h +94 -0
- data/ext/ggml/src/ggml-amx/ggml-amx.cpp +446 -0
- data/ext/ggml/src/ggml-amx/mmq.cpp +2510 -0
- data/ext/ggml/src/ggml-amx/mmq.h +17 -0
- data/ext/ggml/src/ggml-backend-impl.h +256 -0
- data/ext/ggml/src/ggml-backend-reg.cpp +552 -0
- data/ext/ggml/src/ggml-backend.cpp +1999 -0
- data/ext/ggml/src/ggml-blas/ggml-blas.cpp +517 -0
- data/ext/ggml/src/ggml-cann/acl_tensor.cpp +175 -0
- data/ext/ggml/src/ggml-cann/acl_tensor.h +258 -0
- data/ext/ggml/src/ggml-cann/aclnn_ops.cpp +3427 -0
- data/ext/ggml/src/ggml-cann/aclnn_ops.h +592 -0
- data/ext/ggml/src/ggml-cann/common.h +286 -0
- data/ext/ggml/src/ggml-cann/ggml-cann.cpp +2188 -0
- data/ext/ggml/src/ggml-cann/kernels/ascendc_kernels.h +19 -0
- data/ext/ggml/src/ggml-cann/kernels/dup.cpp +236 -0
- data/ext/ggml/src/ggml-cann/kernels/get_row_f16.cpp +197 -0
- data/ext/ggml/src/ggml-cann/kernels/get_row_f32.cpp +190 -0
- data/ext/ggml/src/ggml-cann/kernels/get_row_q4_0.cpp +204 -0
- data/ext/ggml/src/ggml-cann/kernels/get_row_q8_0.cpp +191 -0
- data/ext/ggml/src/ggml-cann/kernels/quantize_f16_q8_0.cpp +218 -0
- data/ext/ggml/src/ggml-cann/kernels/quantize_f32_q8_0.cpp +216 -0
- data/ext/ggml/src/ggml-cann/kernels/quantize_float_to_q4_0.cpp +295 -0
- data/ext/ggml/src/ggml-common.h +1853 -0
- data/ext/ggml/src/ggml-cpu/amx/amx.cpp +220 -0
- data/ext/ggml/src/ggml-cpu/amx/amx.h +8 -0
- data/ext/ggml/src/ggml-cpu/amx/common.h +91 -0
- data/ext/ggml/src/ggml-cpu/amx/mmq.cpp +2511 -0
- data/ext/ggml/src/ggml-cpu/amx/mmq.h +10 -0
- data/ext/ggml/src/ggml-cpu/cpu-feats-x86.cpp +323 -0
- data/ext/ggml/src/ggml-cpu/ggml-cpu-aarch64.cpp +4262 -0
- data/ext/ggml/src/ggml-cpu/ggml-cpu-aarch64.h +8 -0
- data/ext/ggml/src/ggml-cpu/ggml-cpu-hbm.cpp +55 -0
- data/ext/ggml/src/ggml-cpu/ggml-cpu-hbm.h +8 -0
- data/ext/ggml/src/ggml-cpu/ggml-cpu-impl.h +386 -0
- data/ext/ggml/src/ggml-cpu/ggml-cpu-quants.c +10835 -0
- data/ext/ggml/src/ggml-cpu/ggml-cpu-quants.h +63 -0
- data/ext/ggml/src/ggml-cpu/ggml-cpu-traits.cpp +36 -0
- data/ext/ggml/src/ggml-cpu/ggml-cpu-traits.h +38 -0
- data/ext/ggml/src/ggml-cpu/ggml-cpu.c +14123 -0
- data/ext/ggml/src/ggml-cpu/ggml-cpu.cpp +622 -0
- data/ext/ggml/src/ggml-cpu/llamafile/sgemm.cpp +1884 -0
- data/ext/ggml/src/ggml-cpu/llamafile/sgemm.h +14 -0
- data/ext/ggml/src/ggml-cuda/vendors/cuda.h +14 -0
- data/ext/ggml/src/ggml-cuda/vendors/hip.h +186 -0
- data/ext/ggml/src/ggml-cuda/vendors/musa.h +134 -0
- data/ext/ggml/src/ggml-impl.h +556 -0
- data/ext/ggml/src/ggml-kompute/ggml-kompute.cpp +2251 -0
- data/ext/ggml/src/ggml-metal/ggml-metal-impl.h +288 -0
- data/ext/ggml/src/ggml-metal/ggml-metal.m +4884 -0
- data/ext/ggml/src/ggml-metal/ggml-metal.metal +6732 -0
- data/ext/ggml/src/ggml-opt.cpp +854 -0
- data/ext/ggml/src/ggml-quants.c +5238 -0
- data/ext/ggml/src/ggml-quants.h +100 -0
- data/ext/ggml/src/ggml-rpc/ggml-rpc.cpp +1406 -0
- data/ext/ggml/src/ggml-sycl/common.cpp +95 -0
- data/ext/ggml/src/ggml-sycl/concat.cpp +196 -0
- data/ext/ggml/src/ggml-sycl/conv.cpp +99 -0
- data/ext/ggml/src/ggml-sycl/convert.cpp +547 -0
- data/ext/ggml/src/ggml-sycl/dmmv.cpp +1023 -0
- data/ext/ggml/src/ggml-sycl/element_wise.cpp +1030 -0
- data/ext/ggml/src/ggml-sycl/ggml-sycl.cpp +4729 -0
- data/ext/ggml/src/ggml-sycl/im2col.cpp +126 -0
- data/ext/ggml/src/ggml-sycl/mmq.cpp +3031 -0
- data/ext/ggml/src/ggml-sycl/mmvq.cpp +1015 -0
- data/ext/ggml/src/ggml-sycl/norm.cpp +378 -0
- data/ext/ggml/src/ggml-sycl/outprod.cpp +56 -0
- data/ext/ggml/src/ggml-sycl/rope.cpp +276 -0
- data/ext/ggml/src/ggml-sycl/softmax.cpp +251 -0
- data/ext/ggml/src/ggml-sycl/tsembd.cpp +72 -0
- data/ext/ggml/src/ggml-sycl/wkv6.cpp +141 -0
- data/ext/ggml/src/ggml-threading.cpp +12 -0
- data/ext/ggml/src/ggml-threading.h +14 -0
- data/ext/ggml/src/ggml-vulkan/ggml-vulkan.cpp +8657 -0
- data/ext/ggml/src/ggml-vulkan/vulkan-shaders/vulkan-shaders-gen.cpp +593 -0
- data/ext/ggml/src/ggml.c +7694 -0
- data/ext/{whisper.h → include/whisper.h} +23 -22
- data/ext/metal-embed.mk +17 -0
- data/ext/metal.mk +6 -0
- data/ext/ruby_whisper.cpp +1492 -9
- data/ext/ruby_whisper.h +10 -0
- data/ext/scripts/get-flags.mk +38 -0
- data/ext/src/coreml/whisper-decoder-impl.h +146 -0
- data/ext/src/coreml/whisper-decoder-impl.m +201 -0
- data/ext/src/coreml/whisper-encoder-impl.h +142 -0
- data/ext/src/coreml/whisper-encoder-impl.m +197 -0
- data/ext/src/coreml/whisper-encoder.h +26 -0
- data/ext/src/openvino/whisper-openvino-encoder.cpp +108 -0
- data/ext/src/openvino/whisper-openvino-encoder.h +31 -0
- data/ext/{whisper.cpp → src/whisper.cpp} +661 -492
- data/extsources.rb +6 -0
- data/lib/whisper/model/uri.rb +157 -0
- data/lib/whisper.rb +2 -0
- data/tests/helper.rb +7 -0
- data/tests/jfk_reader/.gitignore +5 -0
- data/tests/jfk_reader/extconf.rb +3 -0
- data/tests/jfk_reader/jfk_reader.c +68 -0
- data/tests/test_callback.rb +160 -0
- data/tests/test_error.rb +20 -0
- data/tests/test_model.rb +71 -0
- data/tests/test_package.rb +31 -0
- data/tests/test_params.rb +160 -0
- data/tests/test_segment.rb +83 -0
- data/tests/test_whisper.rb +211 -123
- data/whispercpp.gemspec +36 -0
- metadata +137 -11
- 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 = */ ®,
|
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 ®
|
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)
|